爬虫之selenium使用

扶醉桌前 提交于 2019-12-24 13:00:59

详细使用链接: 点击链接

 

selenium介绍:

 

selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题

 

selenium本质是通过驱动浏览器,完全模拟浏览器的操作,比如跳转、输入、点击、下拉等,来拿到网页渲染之后的结果,可支持多种常见的浏览器

 

from selenium import webdriverbrowser=webdriver.Chrome()browser=webdriver.Firefox()browser=webdriver.PhantomJS()browser=webdriver.Safari()browser=webdriver.Edge()

 

官网:http://selenium-python.readthedocs.io

 

环境搭建

 

1.在python中使用selenium需要先安装对应的模块

 

pip install selenium

 

2.selenium的原理是操作驱动浏览器来完成对目标页面的请求与渲染,所以需要下载对应的浏览器驱动程序,推荐使用chrome

 

镜像地址:https://npm.taobao.org/mirrors/chromedriver/

 

需要注意的是,驱动程序版本需要与浏览器版本对应,你可以打开chrome的关于浏览器查看到具体版本。

 

 

 

驱动与浏览器的版本对应关系

 

ChromeDriver v2.45 (2018-12-10)----------Supports Chrome v70-72 ChromeDriver v2.44 (2018-11-19)----------Supports Chrome v69-71 ChromeDriver v2.43 (2018-10-16)----------Supports Chrome v69-71 ChromeDriver v2.42 (2018-09-13)----------Supports Chrome v68-70 ChromeDriver v2.41 (2018-07-27)----------Supports Chrome v67-69 ChromeDriver v2.40 (2018-06-07)----------Supports Chrome v66-68 ChromeDriver v2.39 (2018-05-30)----------Supports Chrome v66-68 ChromeDriver v2.38 (2018-04-17)----------Supports Chrome v65-67 ChromeDriver v2.37 (2018-03-16)----------Supports Chrome v64-66 ChromeDriver v2.36 (2018-03-02)----------Supports Chrome v63-65 ChromeDriver v2.35 (2018-01-10)----------Supports Chrome v62-64

 

在无GUI系统下的使用方法

 

如果你的操作系统没有GUI(图形界面),则需要使用无界面的浏览器来搭配selenium使用,有两种方案可选

 

1.使用phantomJS

 

#安装:selenium+phantomjs#pip3 install selenium#下载phantomjs,解压后把phantomjs.exe放在项目目录中或是添加到系统环境变量中#下载链接:http://phantomjs.org/download.htmlfrom selenium import webdriverdriver=webdriver.PhantomJS() #无界面浏览器driver.get('https://www.baidu.com')driver.page_sourcedriver.close() #关闭浏览器,回收资源

 

目前phantomJS已经停止了更新维护,幸好Chrome 出来救场了, 是的selenium再次成为了反爬虫 Team 的噩梦

 

自Google 发布 chrome 59 / 60 正式版 开始便支持Headless mode

 

这意味着在无 GUI 环境下, PhantomJS 不再是唯一选择

 

2.使用chrome并设置为无GUI模式

 

from selenium import webdriverfrom selenium.webdriver.chrome.options import Optionschrome_options = Options()chrome_options.add_argument('window-size=1920x3000') #指定浏览器分辨率chrome_options.add_argument('--disable-gpu') #谷歌文档提到需要加上这个属性来规避bugchrome_options.add_argument('--hide-scrollbars') #隐藏滚动条, 应对一些特殊页面chrome_options.add_argument('blink-settings=imagesEnabled=false') #不加载图片, 可以提升速度chrome_options.add_argument('--headless') #浏览器不提供可视化页面. linux下如果系统如果无界面不加这条会启动失败​driver=webdriver.Chrome("驱动绝对路径 如果环境变量中有则可以不写",chrome_options=chrome_options)driver.get('https://www.baidu.com')print('hao123' in driver.page_source)driver.close() #切记关闭浏览器,回收资源#selenium+谷歌浏览器headless模式

 

基本使用

 

from selenium import webdriverfrom selenium.webdriver import ActionChainsfrom selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTORfrom selenium.webdriver.common.keys import Keys #键盘按键操作from selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素​browser=webdriver.Chrome()try:    browser.get('https://www.baidu.com')​    input_tag=browser.find_element_by_id('kw')    input_tag.send_keys('美女') #python2中输入中文错误,字符串前加个u    input_tag.send_keys(Keys.ENTER) #输入回车​    wait=WebDriverWait(browser,10)    wait.until(EC.presence_of_element_located((By.ID,'content_left'))) #等到id为content_left的元素加载完毕,最多等10秒        print(browser.page_source)    print(browser.current_url)    print(browser.get_cookies())​finally:    browser.close()

 

查找元素

 

#官网链接:http://selenium-python.readthedocs.io/locating-elements.htmlfrom selenium import webdriverfrom selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTORfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素import time​driver=webdriver.Chrome()driver.get('https://www.baidu.com')wait=WebDriverWait(driver,10)​try:    #===============所有方法===================    # 1、find_element_by_id    # 2、find_element_by_link_text    # 3、find_element_by_partial_link_text    # 4、find_element_by_tag_name    # 5、find_element_by_class_name    # 6、find_element_by_name    # 7、find_element_by_css_selector    # 8、find_element_by_xpath    # 强调:    # 1、上述均可以改写成find_element(By.ID,'kw')的形式    # 2、find_elements_by_xxx的形式是查找到多个元素,结果为列表​    #===============示范用法===================    # 1、find_element_by_id    print(driver.find_element_by_id('kw'))​    # 2、find_element_by_link_text    # login=driver.find_element_by_link_text('登录')    # login.click()​    # 3、find_element_by_partial_link_text    login=driver.find_elements_by_partial_link_text('录')[0]    login.click()​    # 4、find_element_by_tag_name    print(driver.find_element_by_tag_name('a'))​    # 5、find_element_by_class_name    button=wait.until(EC.element_to_be_clickable((By.CLASS_NAME,'tang-pass-footerBarULogin')))    button.click()​    # 6、find_element_by_name    input_user=wait.until(EC.presence_of_element_located((By.NAME,'userName')))    input_pwd=wait.until(EC.presence_of_element_located((By.NAME,'password')))    commit=wait.until(EC.element_to_be_clickable((By.ID,'TANGRAM__PSP_10__submit')))​    input_user.send_keys('18611453110')    input_pwd.send_keys('xxxxxx')    commit.click()​    # 7、find_element_by_css_selector    driver.find_element_by_css_selector('#kw')​    # 8、find_element_by_xpath​    time.sleep(5)​finally:    driver.close()

 

获取标签属性

 

from selenium import webdriverfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素​browser=webdriver.Chrome()browser.get('https://www.amazon.cn/')​wait=WebDriverWait(browser,10)wait.until(EC.presence_of_element_located((By.ID,'cc-lm-tcgShowImgContainer')))​tag=browser.find_element(By.CSS_SELECTOR,'#cc-lm-tcgShowImgContainer img')​#获取标签属性,print(tag.get_attribute('src'))#获取标签ID,位置,名称,大小(了解)print(tag.id)print(tag.location)print(tag.tag_name)print(tag.size)​browser.close()

 

等待元素加载

 

#1、selenium只是模拟浏览器的行为,而浏览器解析页面是需要时间的(执行css,js),一些元素可能需要过一段时间才能加载出来,为了保证能查找到元素,必须等待​#2、等待的方式分两种:隐式等待:在browser.get('xxx')前就设置,针对所有元素有效显式等待:在browser.get('xxx')之后设置,只针对某个元素有效

 

隐式等待

 

每次都会等待网页全部加载完成再进行下一步

 

from selenium import webdriverbrowser=webdriver.Chrome()​#隐式等待:在查找所有元素时,如果尚未被加载,则等10秒browser.implicitly_wait(10)​browser.get('https://www.baidu.com')​​input_tag=browser.find_element_by_id('kw')input_tag.send_keys('美女')input_tag.send_keys(Keys.ENTER)​contents=browser.find_element_by_id('content_left') #没有等待环节而直接查找,找不到则会报错print(contents)​browser.close()

 

显式等待

 

明确的指定要等待哪一个元素出现

 

from selenium import webdriverfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素​browser=webdriver.Chrome()browser.get('https://www.baidu.com')​​input_tag=browser.find_element_by_id('kw')input_tag.send_keys('美女')input_tag.send_keys(Keys.ENTER)​#显式等待:显式地等待某个元素被加载wait=WebDriverWait(browser,10)wait.until(EC.presence_of_element_located((By.ID,'content_left')))​contents=browser.find_element(By.CSS_SELECTOR,'#content_left')print(contents)​browser.close()

 

交互操作

 

清空输入框

 

from selenium import webdriverfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素​browser=webdriver.Chrome()browser.get('https://www.amazon.cn/')wait=WebDriverWait(browser,10)​input_tag=wait.until(EC.presence_of_element_located((By.ID,'twotabsearchtextbox')))input_tag.send_keys('iphone 8')button=browser.find_element_by_css_selector('#nav-search > form > div.nav-right > div > input')button.click()​import timetime.sleep(3)​input_tag=browser.find_element_by_id('twotabsearchtextbox')input_tag.clear() #清空输入框input_tag.send_keys('iphone7plus') # 输入文字button=browser.find_element_by_css_selector('#nav-search > form > div.nav-right > div > input')button.click() # 点击按钮

 

切换fream

 

#frame相当于一个单独的网页,在父frame里是无法直接查看到子frame的元素的,必须switch_to_frame切到该frame下,才能进一步查找​from selenium import webdriver​try:    browser=webdriver.Chrome()    browser.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')    browser.switch_to.frame('iframeResult') #切换到id为iframeResult的frame    tag1=browser.find_element_by_id('droppable')    print(tag1)​    # tag2=browser.find_element_by_id('textareaCode') #报错,在子frame里无法查看到父frame的元素    browser.switch_to.parent_frame() #切回父frame,就可以查找到了    tag2=browser.find_element_by_id('textareaCode')    print(tag2)​finally:    browser.close()

 

动作链

 

from selenium import webdriverfrom selenium.webdriver import ActionChainsfrom selenium.webdriver.support.wait import WebDriverWait  # 等待页面加载某些元素​driver = webdriver.Chrome()driver.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')wait=WebDriverWait(driver,3)try:    driver.switch_to.frame('iframeResult') ##切换到iframeResult    sourse=driver.find_element_by_id('draggable')    target=driver.find_element_by_id('droppable')​    #方式一:基于同一个动作链串行执行    # actions=ActionChains(driver) #拿到动作链对象    # actions.drag_and_drop(sourse,target) #把动作放到动作链中 一次性移动到目标位置    # actions.perform() # 执行​    #方式二:线性移动    ActionChains(driver).click_and_hold(sourse).perform()    distance=target.location['x']-sourse.location['x']​    track=0    while track < distance:        ActionChains(driver).move_by_offset(xoffset=2,yoffset=0).perform()        track+=2    ActionChains(driver).release().perform()finally:    driver.close()

 

执行JS

 

在交互动作比较难实现的时候可以自己写JS

 

from selenium import webdrivertry:    browser=webdriver.Chrome()    browser.get('https://www.baidu.com')    browser.execute_script('alert("hello world")') #打印警告finally:    browser.close()

 

前进后退

 

#模拟浏览器的前进后退import timefrom selenium import webdriver​browser=webdriver.Chrome()browser.get('https://www.baidu.com')browser.get('https://www.taobao.com')browser.get('http://www.sina.com.cn/')​browser.back()time.sleep(4)browser.forward()browser.close()

 

选项卡切换

 

#选项卡管理:切换选项卡,有js的方式windows.open,有windows快捷键:ctrl+t等,最通用的就是js的方式import timefrom selenium import webdriver​browser=webdriver.Chrome()browser.get('https://www.baidu.com')browser.execute_script('window.open()')​print(browser.window_handles) #获取所有的选项卡browser.switch_to_window(browser.window_handles[1])browser.get('https://www.taobao.com')time.sleep(10)browser.switch_to_window(browser.window_handles[0])browser.get('https://www.sina.com.cn')browser.close()

 

xpath

 

xpath XML_Path是一种通用的查找元素方式,也在scrapy模块中使用

 

doc='''<html> <head>  <base href='http://example.com/' />  <title>Example website</title> </head> <body>  <div id='images'>   <a href='image1.html'>Name: My image 1 <br /><img src='image1_thumb.jpg' /></a>   <a href='image2.html'>Name: My image 2 <br /><img src='image2_thumb.jpg' /></a>   <a href='image3.html'>Name: My image 3 <br /><img src='image3_thumb.jpg' /></a>   <a href='image4.html'>Name: My image 4 <br /><img src='image4_thumb.jpg' /></a>   <a href='image5.html' class='li li-item' name='items'>Name: My image 5 <br /><img src='image5_thumb.jpg' /></a>   <a href='image6.html' name='items'><span><h5>test</h5></span>Name: My image 6 <br /><img src='image6_thumb.jpg' /></a>  </div> </body></html>'''from lxml import etree​html=etree.HTML(doc)# html=etree.parse('search.html',etree.HTMLParser())​#/一个斜杠表示子级标签#//一个斜杠表示子孙标签​# 1 所有节点# a=html.xpath('//*')# 2 指定节点(结果为列表)# a=html.xpath('//head')# 3 子节点,子孙节点# a=html.xpath('//div/a')# a=html.xpath('//body/a') #无数据# a=html.xpath('//body//a')# 4 父节点# a=html.xpath('//body//a[@href="image1.html"]/..')# a=html.xpath('//body//a[1]/..')# 也可以这样# a=html.xpath('//body//a[1]/parent::*')# 5 属性匹配# a=html.xpath('//body//a[@href="image1.html"]')​# 6 文本获取# a=html.xpath('//body//a[@href="image1.html"]/text()')​# 7 属性获取# a=html.xpath('//body//a/@href')# # 注意从1 开始取(不是从0)# a=html.xpath('//body//a[1]/@href')# 8 属性多值匹配#  a 标签有多个class类,直接匹配就不可以了,需要用contains# a=html.xpath('//body//a[@class="li"]')# a=html.xpath('//body//a[contains(@class,"li")]')# a=html.xpath('//body//a[contains(@class,"li")]/text()')# 9 多属性匹配# a=html.xpath('//body//a[contains(@class,"li") or @name="items"]')# a=html.xpath('//body//a[contains(@class,"li") and @name="items"]/text()')# # a=html.xpath('//body//a[contains(@class,"li")]/text()')# 10 按序选择# a=html.xpath('//a[2]/text()')# a=html.xpath('//a[2]/@href')# 取最后一个# a=html.xpath('//a[last()]/@href')# 位置小于3的# a=html.xpath('//a[position()<3]/@href')# 倒数第二个# a=html.xpath('//a[last()-2]/@href')# 11 节点轴选择# ancestor:祖先节点# 使用了* 获取所有祖先节点# a=html.xpath('//a/ancestor::*')# # 获取祖先节点中的div# a=html.xpath('//a/ancestor::div')# attribute:属性值# a=html.xpath('//a[1]/attribute::*')# child:直接子节点# a=html.xpath('//a[1]/child::*')# descendant:所有子孙节点# a=html.xpath('//a[6]/descendant::*')# following:当前节点之后所有节点# a=html.xpath('//a[1]/following::*')# a=html.xpath('//a[1]/following::*[1]/@href')# following-sibling:当前节点之后同级节点# a=html.xpath('//a[1]/following-sibling::*')# a=html.xpath('//a[1]/following-sibling::a')# a=html.xpath('//a[1]/following-sibling::*[2]')# a=html.xpath('//a[1]/following-sibling::*[2]/@href')

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!