首页 > 其他 > 详细

爬虫框架-selenium

时间:2020-01-01 21:02:20      阅读:100      评论:0      收藏:0      [点我收藏+]

0|1selenium介绍:


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

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

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

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

0|1环境搭建


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.html from selenium import webdriver driver=webdriver.PhantomJS() #无界面浏览器 driver.get(‘https://www.baidu.com‘) driver.page_source driver.close() #关闭浏览器,回收资源

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

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

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

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

from selenium import webdriver from selenium.webdriver.chrome.options import Options chrome_options = Options() chrome_options.add_argument(‘window-size=1920x3000‘) #指定浏览器分辨率 chrome_options.add_argument(‘--disable-gpu‘) #谷歌文档提到需要加上这个属性来规避bug chrome_options.add_argument(‘--hide-scrollbars‘) #隐藏滚动条, 应对一些特殊页面 chrome_options.add_argument(‘blink-settings=imagesEnabled=false‘) #不加载图片, 可以提升速度 chrome_options.add_argument(‘--headless‘) #浏览器不提供可视化页面. linux下如果系统如果无界面不加这条会启动失败 chrome_options.add_experimental_option(‘excludeSwitches‘, [‘enable-automation‘])#取消浏览器驱动提示 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 webdriver from selenium.webdriver import ActionChains from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR from selenium.webdriver.common.keys import Keys #键盘按键操作 from selenium.webdriver.support import expected_conditions as EC from 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.html from selenium import webdriver from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR from selenium.webdriver.support import expected_conditions as EC from 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 webdriver from selenium.webdriver.support import expected_conditions as EC from 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 webdriver browser=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 webdriver from selenium.webdriver.support import expected_conditions as EC from 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 webdriver from selenium.webdriver.support import expected_conditions as EC from 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 time time.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 webdriver from selenium.webdriver import ActionChains from 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 webdriver try: browser=webdriver.Chrome() browser.get(‘https://www.baidu.com‘) browser.execute_script(‘alert("hello world")‘) #打印警告 finally: browser.close()

前进后退

#模拟浏览器的前进后退 import time from 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 time from 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‘)

__EOF__

作  者CoderJerry
出  处https://www.cnblogs.com/yangyuanhu/p/11224568.html
关于博主:热爱技术,喜欢专研。评论和私信会在第一时间回复。或者直接私信我。
版权声明:署名 - 非商业性使用 - 禁止演绎,协议普通文本 | 协议法律文本
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!

爬虫(Spider),反爬虫(Anti-Spider),反反爬虫(Anti-Anti-Spider) 之间恢宏壮阔的斗争...

  • 小莫想要某站上所有的电影,写了标准的爬虫(基于HttpClient库),不断地遍历某站的电影列表页面,根据 Html 分析电影名字存进自己的数据库。

  • 这个站点的运维小黎发现某个时间段请求量陡增,分析日志发现都是 IP(xxx.xxx.xxx.xxx)这个用户,并且 user-agent 还是 Python-urllib/2.7 ,基于这两点判断非人类后直接在服务器上封杀。

  • 小莫电影只爬了一半,于是也针对性的变换了下策略:1. user-agent 模仿百度("Baiduspider..."),2. IP每爬半个小时就换一个IP代理。

  • 小黎也发现了对应的变化,于是在服务器上设置了一个频率限制,每分钟超过120次请求的再屏蔽IP。 同时考虑到百度家的爬虫有可能会被误伤,想想市场部门每月几十万的投放,于是写了个脚本,通过 hostname 检查下这个 ip 是不是真的百度家的,对这些 ip 设置一个白名单。

  • 小莫发现了新的限制后,想着我也不急着要这些数据,留给服务器慢慢爬吧,于是修改了代码,随机1-3秒爬一次,爬10次休息10秒,每天只在8-12,18-20点爬,隔几天还休息一下。

  • 小黎看着新的日志头都大了,再设定规则不小心会误伤真实用户,于是准备换了一个思路,当3个小时的总请求超过50次的时候弹出一个验证码弹框,没有正确输入的话就把 IP 记录进黑名单。

  • 小莫看到验证码有些傻脸了,不过也不是没有办法,先去学习了图像识别(关键词 PIL,tesseract),再对验证码进行了二值化,分词,模式训练之后,总之最后识别了小黎的验证码(关于验证码,验证码的识别,验证码的反识别也是一个恢弘壮丽的斗争史...),之后爬虫又跑了起来。

  • 小黎是个不折不挠的好同学,看到验证码被攻破后,和开发同学商量了变化下开发模式,数据并不再直接渲染,而是由前端同学异步获取,并且通过 JavaScript 的加密库生成动态的 token,同时加密库再进行混淆。

  • 混淆过的加密库就没有办法了么?当然不是,可以慢慢调试,找到加密原理,不过小莫不准备用这么耗时耗力的方法,他放弃了基于 HttpClient的爬虫,选择了内置浏览器引擎的爬虫(关键词:PhantomJS,Selenium),在浏览器引擎运行页面,直接获取了正确的结果,又一次拿到了对方的数据。

  • 小黎:.....

Selenium

 Selenium是一个Web的自动化测试工具,最初是为网站自动化测试而开发的,类型像我们玩游戏用的按键精灵,可以按指定的命令自动操作,不同是Selenium 可以直接运行在浏览器上,它支持所有主流的浏览器(包括PhantomJS这些无界面的浏览器)。

Selenium 可以根据我们的指令,让浏览器自动加载页面,获取需要的数据,甚至页面截屏,或者判断网站上某些动作是否发生。

Selenium 自己不带浏览器,不支持浏览器的功能,它需要与第三方浏览器结合在一起才能使用.

下载selenium webdriver ‘geckodriver.exe’,下载好后放到python目录里面

firefox的目录也要添加到环境变量中

Selenium 库里有个叫 WebDriver 的 API。WebDriver 有点儿像可以加载网站的浏览器,但是它也可以像 BeautifulSoup 或者其他 Selector 对象一样用来查找页面元素,与页面上的元素进行交互 (发送文本、点击等),以及执行其他动作来运行网络爬虫。

selenium快速入门

技术分享图片
#!/usr/bin/env python
# -*- coding:utf-8 -*-

from selenium import webdriver

# 要想调用键盘按键操作需要引入keys包
from selenium.webdriver.common.keys import Keys

#创建浏览器对象
driver = webdriver.Firefox()

driver.get("http://www.baidu.com")

#打印页面标题“百度一下你就知道”
print driver.title

#生成当前页面快照
driver.save_screenshot("baidu.png")

# id="kw"是百度搜索框,输入字符串“微博”,跳转到搜索中国页面
driver.find_element_by_id("kw").send_keys(u"微博")

# id="su"是百度搜索按钮,click() 是模拟点击
driver.find_element_by_id("su").click()

# 获取新的页面快照
driver.save_screenshot(u"微博.png")

# 打印网页渲染后的源代码
print driver.page_source

# 获取当前页面Cookie
print driver.get_cookies()

# ctrl+a 全选输入框内容
driver.find_element_by_id("kw").send_keys(Keys.CONTROL,a)

# ctrl+x 剪切输入框内容
driver.find_element_by_id("kw").send_keys(Keys.CONTROL,x)

# 输入框重新输入内容
driver.find_element_by_id("kw").send_keys("test")

# 模拟Enter回车键
driver.find_element_by_id("su").send_keys(Keys.RETURN)

# 清除输入框内容
driver.find_element_by_id("kw").clear()

# 生成新的页面快照
driver.save_screenshot("test.png")

# 获取当前url
print driver.current_url

# 关闭当前页面,如果只有一个页面,会关闭浏览器
# driver.close()

# 关闭浏览器
driver.quit()
技术分享图片

1.页面操作

假如有下面的输入框

<input type="text" name="user-name" id="passwd-id" />

寻找方法

技术分享图片
# 获取id标签值
element = driver.find_element_by_id("passwd-id")
# 获取name标签值
element = driver.find_element_by_name("user-name")
# 获取标签名值
element = driver.find_elements_by_tag_name("input")
# 也可以通过XPath来匹配
element = driver.find_element_by_xpath("//input[@id=‘passwd-id‘]")
技术分享图片

2.定位元素的方法

技术分享图片
find_element_by_id
find_elements_by_name
find_elements_by_xpath
find_elements_by_link_text
find_elements_by_partial_link_text
find_elements_by_tag_name
find_elements_by_class_name
find_elements_by_css_selector
技术分享图片

3.鼠标动作

技术分享图片
#!/usr/bin/env python
# -*- coding:utf-8 -*-

from selenium import webdriver

# 要想调用键盘按键操作需要引入keys包
from selenium.webdriver.common.keys import Keys
from selenium.webdriver import ActionChains

#创建浏览器对象
driver = webdriver.Firefox()

driver.get("http://www.baidu.com")

#鼠标移动到某处
action1 = driver.find_element_by_id("su")
ActionChains(driver).move_to_element(action1).perform()

#鼠标移动到某处单击
action2 = driver.find_element_by_id("su")
ActionChains(driver).move_to_element(action2).click(action2).perform()

#鼠标移动到某处双击
action3 = driver.find_element_by_id("su")
ActionChains(driver).move_to_element(action3).double_click(action3).perform()

# 鼠标移动到某处右击
action4 = driver.find_element_by_id("su")
ActionChains(driver).move_to_element(action4).context_click(action4).perform()
技术分享图片

4.Select表单

遇到下来框需要选择操作时,Selenium专门提供了Select类来处理下拉框

技术分享图片
# 导入 Select 类
from selenium.webdriver.support.ui import Select

# 找到 name 的选项卡
select = Select(driver.find_element_by_name(status))

# 
select.select_by_index(1)
select.select_by_value("0")
select.select_by_visible_text(u"xxx")
技术分享图片

以上是三种选择下拉框的方式,它可以根据索引来选择,可以根据值来选择,可以根据文字来选择。注意:

  • index 索引从 0 开始
  • value是option标签的一个属性值,并不是显示在下拉框中的值
  • visible_text是在option标签文本的值,是显示在下拉框的值

全部取消方法

select.deselect_all()

5.弹窗处理

当页面出现了弹窗提示

alert = driver.switch_to_alert()

6.页面切换

一个浏览器肯定会有很多窗口,所以我们肯定要有方法来实现窗口的切换。切换窗口的方法如下:

driver.switch_to.window("this is window name")

7.页面前进和后退

操作页面的前进和后退功能:

driver.forward()     #前进
driver.back()        # 后退

实例 模拟登陆douban网站

技术分享图片
#!/usr/bin/env python
# -*- coding:utf-8 -*-

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time

driver = webdriver.Firefox()
driver.get("http://www.douban.com")

# 输入账号密码
driver.find_element_by_name("form_email").send_keys("158xxxxxxxx")
driver.find_element_by_name("form_password").send_keys("zhxxxxxxxx")

# 模拟点击登录
driver.find_element_by_xpath("//input[@class=‘bn-submit‘]").click()

# 等待3秒
time.sleep(3)

# 生成登陆后快照
driver.save_screenshot(u"douban.png")

driver.quit()
技术分享图片

 动态页面模拟点击--->>>爬取斗鱼所有房间名,观众人数

(1)首先分析‘’下一页‘’的class变化,如果不是最后一页的时候,‘下一页’的class如下

 技术分享图片

(2)如果到了最后一页,‘下一页’变为隐藏,点击不了,class变为如下

技术分享图片

(3)找到个房间的名字和观众人数的class

技术分享图片

(4)代码

技术分享图片
#!/usr/bin/env python
# -*- coding:utf-8 -*-

import unittest
from selenium import webdriver
from bs4 import BeautifulSoup as bs

class douyu(unittest.TestCase):
    # 初始化方法,必须是setUp()
    def setUp(self):
        self.driver = webdriver.Firefox()
        self.num = 0
        self.count = 0

    # 测试方法必须有test字样开头
    def testDouyu(self):
        self.driver.get("https://www.douyu.com/directory/all")

        while True:
            soup = bs(self.driver.page_source, "lxml")
            # 房间名, 返回列表
            names = soup.find_all("h3", {"class" : "ellipsis"})
            # 观众人数, 返回列表
            numbers = soup.find_all("span", {"class" :"dy-num fr"})

            # zip(names, numbers) 将name和number这两个列表合并为一个元组 : [(1, 2), (3, 4)...]
            for name, number in zip(names, numbers):
                print u"观众人数: -" + number.get_text().strip() + u"-\t房间名: " + name.get_text().strip()
                self.num += 1
                #self.count += int(number.get_text().strip())

            # 如果在页面源码里找到"下一页"为隐藏的标签,就退出循环
            if self.driver.page_source.find("shark-pager-disable-next") != -1:
                    break

            # 一直点击下一页
            self.driver.find_element_by_class_name("shark-pager-next").click()

    # 测试结束执行的方法
    def tearDown(self):
        # 退出Firefox()浏览器
        print "当前网站直播人数" + str(self.num)
        print "当前网站观众人数" + str(self.count)
        self.driver.quit()

if __name__ == "__main__":
    # 启动测试模块
    unittest.main()
技术分享图片

爬取的结果:

技术分享图片

 

Selenium使用

  Selenium是一个自动化测试工具,可以驱动浏览器器执行特定的动作,如点击,下拉等。同时还可以获取浏览器当前呈现页面的源代码,可见即可爬。

1.准备

  我们使用谷歌Chrome浏览器为例子,在开始之前需要安装Chrome浏览器并配置ChromeDriver。而且还需要安装Python的Selenium库。

2.基本使用

技术分享图片
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

# 声明浏览器对象,将chromedriver驱动放在chrome浏览器安装目录下,指定驱动的绝对路径
browser = webdriver.Chrome(executable_path=rD:\Google\Chrome\Application\chromedriver)
try:
    browser.get(http://www.baidu.com)      
    keyword = browser.find_element_by_id(kw)
    keyword.send_keys(Python)
    keyword.send_keys(Keys.ENTER)
    wait = WebDriverWait(browser, 10)
    wait.until(EC.presence_of_element_located((By.ID, content_left)))
    print(browser.current_url)
    print(browser.get_cookies())
    print(browser.page_source)
finally:
    browser.close()
技术分享图片

  运行结果:

技术分享图片
https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=Python&rsv_pq=962442bf0007ea18&rsv_t=753aQptBMQwu82UDxwDFL9MEWvHNLNqjPznV4pNUSDP%2Bimq4HPgY91krrlM&rqlang=cn&rsv_enter=1&rsv_sug3=6&rsv_sug2=0&inputT=125&rsv_sug4=125
[{domain: .baidu.com, httpOnly: False, name: H_PS_PSSID, path: /, secure: False, value: 1465_21104_29135_28518_29098_28831_28585_26350_29133}, {domain: .baidu.com, httpOnly: False, name: delPer, path: /, secure: False, value: 0}, {domain: .baidu.com, expiry: 3707115919.146628, httpOnly: False, name: BAIDUID, path: /, secure: False, value: 3A3A4CD3F97428EF73BA5E8B09ECB3C3:FG=1}, {domain: .baidu.com, expiry: 3707115919.14668, httpOnly: False, name: PSTM, path: /, secure: False, value: 1559632270}, {domain: .baidu.com, expiry: 3707115919.146663, httpOnly: False, name: BIDUPSID, path: /, secure: False, value: 3A3A4CD3F97428EF73BA5E8B09ECB3C3}, {domain: www.baidu.com, httpOnly: False, name: BD_HOME, path: /, secure: False, value: 0}, {domain: .baidu.com, expiry: 1559718674.348966, httpOnly: False, name: BDORZ, path: /, secure: False, value: B490B5EBF6F3CD402E515D22BCDA1598}, {domain: www.baidu.com, expiry: 1560496273, httpOnly: False, name: BD_UPN, path: /, secure: False, value: 12314753}, {domain: www.baidu.com, httpOnly: False, name: BD_CK_SAM, path: /, secure: False, value: 1}, {domain: www.baidu.com, expiry: 1559634866, httpOnly: False, name: H_PS_645EC, path: /, secure: False, value: 1058c7aSaGElrxQn6SZOATLVXWtCzFAGCMEiW5OevaJTsJ938%2BGyVo1%2B72k}, {domain: .baidu.com, httpOnly: False, name: PSINO, path: /, secure: False, value: 5}, {domain: www.baidu.com, httpOnly: False, name: BDSVRTM, path: /, secure: False, value: 173}]
<!DOCTYPE html><!--STATUS OK--><html xmlns="http://www.w3.org/1999/xhtml"><head><script charset="utf-8" async="" src="https://ss0.bdstatic.com/-0U0bnSm1A5BphGlnYG/tam-ogel/5d4e9b24-dcc5-483a-b6da-be1e9e621891.js"></script>
    
    <meta http-equiv="content-type" content="text/html;charset=utf-8" /><style data-for="result" id="css_result" type="text/css">body{color:#333;background:#fff;padding:6px 0 0;margin:0;position:relative;min-width:900px}body,th,td,.p1,.p2{font-family:arial}p,form,ol,ul,li,dl,dt,dd,h3{margin:0;padding:0;list-style:none}input{padding-top:0;padding-bottom:0;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}table,img{border:0}td{font-size:9pt;line-height:18px}em{font-style:normal;color:#c00}a em{text-decoration:underline}cite{font-style:normal;......
技术分享图片

  运行代码后发现,会自动弹出一个Chrome浏览器,首先跳转到百度,然后输入Python,接着跳转到搜索结果。结果加载出来后,控制台会打印当前url,Cookies和网页源码。可以看到我们得到的都是浏览器中真实显示的内容。这样使用Selenium驱动浏览器加载网页可以直接获取到动态渲染的结果。

3.查找节点

  Selenium可以驱动浏览器完成各种操作,比如点击模拟,表单填写。例如,我们如果想要在某一输入框内输入文本,首先需要找到这个输入框的位置,也就是在网页中的所在节点的位置。

  ?单个节点

  技术分享图片

  想要在百度搜索框中输入文本,首先观察它的源码。我们可以发它的name属性为wd,id为kw,还有一些其他属性。此时我们可以用多种方式来获取它。

技术分享图片
# 单个节点
browser.get(http://www.baidu.com)
input1 = browser.find_element_by_id(kw)                   # 使用属性选择
input2 = browser.find_element_by_css_selector(#kw)        # 使用css选择
input3 = browser.find_element_by_xpath(//*[@id="kw"])     # 使用xpath选择
print(input1)
print(input2)
print(input3)
browser.close()
技术分享图片

   运行结果:

技术分享图片
<selenium.webdriver.remote.webelement.WebElement (session="77121972a5b1ff253e30e6912a609acc", element="0.1322124037138812-1")>
<selenium.webdriver.remote.webelement.WebElement (session="77121972a5b1ff253e30e6912a609acc", element="0.1322124037138812-1")>
<selenium.webdriver.remote.webelement.WebElement (session="77121972a5b1ff253e30e6912a609acc", element="0.1322124037138812-1")>
技术分享图片

  可以看到三个方式返回的结果是完全一致的。当然还有其他很多方法可以使用。

  ?多个节点

    如果查找的目标只有一个,那么完全可以使用find_element()方法,如果有个多目标,find_element()方法只能查找到第一个,要想全部查找到,需要使用find_elements()方法。方法名后面多了一个s。

    比如,想要查找淘宝网左侧导航栏上面的所有条目:

                      技术分享图片

  

# 多个节点,淘宝导航栏条目为例
browser.get(https://www.taobao.com)
items = browser.find_elements_by_css_selector(.service-bd li)
print(items)
browser.close()

    运行结果:

技术分享图片
selenium.webdriver.remote.webelement.WebElement (session="d0d87044954d7497862d2f93b0480667", element="0.5258543885521916-1")>, <selenium.webdriver.remote.webelement.WebElement (session="d0d87044954d7497862d2f93b0480667", element="0.5258543885521916-2")>, <selenium.webdriver.remote.webelement.WebElement (session="d0d87044954d7497862d2f93b0480667", element="0.5258543885521916-3")>, <selenium.webdriver.remote.webelement.WebElement ......
技术分享图片

    这里可以看到,获取的内容为一个列表类型,列表中的每个元素都是WebElement类型。

4.节点操作

  Selenium提供了一些方法来模拟浏览器的动作,输入文字使用send_key()方法,清空使用clear()方法,点击按钮方使用click()方法。 

技术分享图片
# 2.节点交互
import time

browser = webdriver.Chrome(executable_path=rD:\Google\Chrome\Application\chromedriver)
browser.get(http://www.baidu.com)
input_word = browser.find_element_by_id(kw)
input_word.send_keys(apple)
time.sleep(2)
input_word.clear()
input_word.send_keys(cherry)
button = browser.find_element_by_id(su)
time.sleep(3)
button.click()
browser.close()
技术分享图片

5.动作链操作    

  鼠标拖拽,键盘按键等等,这些动作是使用动作链操作来完成的。下面以菜鸟教程的网站为例:

技术分享图片
# 5.动作链操作
from selenium import webdriver
from selenium.webdriver import ActionChains
import time

browser = webdriver.Chrome(executable_path=rD:\Google\Chrome\Application\chromedriver)
url = http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable
browser.get(url)
browser.switch_to.frame(iframeResult)
s1 = browser.find_element_by_css_selector(#draggable)
s2 = browser.find_element_by_css_selector(#droppable)
actions = ActionChains(browser)
actions.drag_and_drop(s1, s2)
actions.perform()
time.sleep(2)
browser.close()
技术分享图片

  执行代码,会打开网站页面,然后自动拖动其中一个拖拽示例拖拽到目标位置。

6.操作JavaScript

  Selenium中模拟操作JavaScript使用execute_script()方法来实现。访问网站,滑动到底部,最后弹出“OK”。 

技术分享图片
# 6.模拟JavaScript操作
from selenium import webdriver
import time

browser = webdriver.Chrome(executable_path=rD:\Google\Chrome\Application\chromedriver)
browser.get(https://www.zhihu.com/explore)
browser.execute_script(window.scrollTo(0,document.body.scrollHeight))
browser.execute_script(alert("OK"))
time.sleep(3)
browser.close()
技术分享图片

7.获取节点信息

  ?获取属性

  使用get_attribute()方法来获取节点属性,先选中这个节点: 

技术分享图片
# 7.1获取属性
browser = webdriver.Chrome(executable_path=rD:\Google\Chrome\Application\chromedriver)
browser.get(https://www.zhihu.com/explore)
logo = browser.find_element_by_id(zh-top-link-logo)
print(logo)
print(logo.get_attribute(class))
browser.close()
技术分享图片

  运行结果:

<selenium.webdriver.remote.webelement.WebElement (session="13c1e08b7569415b9027cdfec9703a0e", element="0.2490095895940252-1")>
zu-top-link-logo
  ?获取文本

  每个WebElement节点都有其text属性,直接调用这个属性就得到其内部的文本信息。 获取百度首页新闻的文本内容。  

# 7.2获取文本信息
browser = webdriver.Chrome(executable_path=rD:\Google\Chrome\Application\chromedriver)
browser.get(http://www.baidu.com)
icons = browser.find_element_by_name(tj_trnews)
print(icons.text)

  运行结果:

新闻
  ?获取id,位置,标签名,大小
技术分享图片
# 7.3获取id,位置,标签名,大小
browser = webdriver.Chrome(executable_path=rD:\Google\Chrome\Application\chromedriver)
browser.get(http://www.baidu.com)
icons = browser.find_element_by_name(tj_trnews)
print(icons.id)
print(icons.location)
print(icons.tag_name)
print(icons.size)
技术分享图片

  运行结果:

0.4808968979713124-1
{x: 557, y: 19}
a
{height: 24, width: 26}

8.切换Frame

  网页中有一种节点叫做iframe,也就是子Frame,相当于页面的子页面,它的结构和外部网页一致。Selenium默认是在父级Frame里面操作,如果页面中还有子Frame,不能直接获取到子页面的数据,需要使用switch_to.frame()切换Frame。

技术分享图片
# 8.切换Frame
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException

browser = webdriver.Chrome(executable_path=rD:\Google\Chrome\Application\chromedriver)
url = http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable
browser.get(url)
browser.switch_to.frame(iframeResult)  
try:
    logo_first = browser.find_element_by_class_name(logo)
except NoSuchElementException:
    print("Failed")
browser.switch_to.parent_frame()  # 切换到父级Frame
logo = browser.find_element_by_class_name(logo)
print(logo)
print(logo.text)
技术分享图片

  运行结果:

Failed
<selenium.webdriver.remote.webelement.WebElement (session="497ccfe660416ed053ba4b08b5c7351f", element="0.03506166807633293-2")>
RUNOOB.COM

9.延时等待

  在Selenium中,get()方法会在网页加载结束后执行,此时获取page_source可能并不是浏览器完全加载的数据。如果有额外的Ajax请求,不一定能获取成功。所有需要延时等待一定时间,确保数据已经加载出来。

  ?隐式等待

  如果Selenium没有在DOM中找到节点,将继续等待,超出设定时间后就会抛出没有节点的异常。

技术分享图片
# 9.延时等待
# 9.1隐式等待:没有找到继续等待,超时抛出异常
browser = webdriver.Chrome(executable_path=rD:\Google\Chrome\Application\chromedriver)
browser.implicitly_wait(10)
browser.get(https://www.zhihu.com/explore)
que = browser.find_element_by_class_name(zu-top-add-question)
print(que)
技术分享图片
  ?显式等待

  指定一个节点,设置最长等待时间。如果规定的时间内加载出来了,就返回要查找的节点;超出时间则抛出异常。  

技术分享图片
# 9.2显式等待
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait


browser = webdriver.Chrome(executable_path=rD:\Google\Chrome\Application\chromedriver)
browser.get(https://www.taobao.com/)
wait = WebDriverWait(browser, 10)
su = wait.until(EC.presence_of_element_located((By.ID, q)))  # 等待条件,节点出现
button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, .btn-search)))  # 等待条件,按钮可以点击
print(su, button)
技术分享图片

  运行结果:

<selenium.webdriver.remote.webelement.WebElement (session="69f58b354be01e63e367e29756e64f18", element="0.005030458042517338-1")> <selenium.webdriver.remote.webelement.WebElement (session="69f58b354be01e63e367e29756e64f18", element="0.005030458042517338-2")>

  如果10秒内没有加载成功,就会抛出TimeoutException异常。

10.窗口管理

  浏览器访问网页时会开启一个个窗口,我们也可以使用Selenium对多个窗口进行操作。

技术分享图片
# 10.窗口管理
import time
from selenium import webdriver


browser = webdriver.Chrome(executable_path=rD:\Google\Chrome\Application\chromedriver)
browser.get(http://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(2)
browser.switch_to.window(browser.window_handles[0])
browser.get(https://www.zhihu.com/explore)
技术分享图片

  window.open()开启新窗口,windo_handlers获取当前开启的所有窗口,返回的是窗口代号的列表。使用switch_to.window()切换窗口。

  先访问百度,然后打开新窗口,再访问淘宝,最后切换回正在访问百度的第一个窗口,接着访问知乎。

11.异常处理

  使用Selenium过程难免会出现异常,例如超时,节点为找到等。一旦出现异常,程序便不会运行了。使用try except语句来捕获异常:

技术分享图片
# 11.异常处理
from selenium import webdriver
from selenium.common.exceptions import TimeoutException, NoSuchElementException


browser = webdriver.Chrome(executable_path=rD:\Google\Chrome\Application\chromedriver)
browser.get(http://www.baidu.com)
try:
    browser.find_element_by_class_name(hello)
except TimeoutException:
    print(Time out)
try:
    browser.find_element_by_class_name(hello)
except NoSuchElementException:
    print(No Element)
finally:
    browser.close()
技术分享图片

 

爬虫框架-selenium

原文:https://www.cnblogs.com/abdm-989/p/12129862.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!