selenium——自动化测试工具,专门为Web应用程序编写的一个验收测试工具,测试其兼容性,功能什么的。然而让虫师们垂涎的并不是以上的种种,而是其通过驱动浏览器获得的解析JavaScript的能力。所以说这货在动态爬取方面简直是挂逼级别的存在,相较于手动分析更简单易用,节省分析打码时间。

虽然selenium因其“超能力”被不少人吹上天了,但是认清利弊,根据需求来选择爬虫工具,还是挺重要的,所以这里简单说下以供参考:

selenium无脑解决动态难题

selenium更耐网页变动

selenium极大提升开发效率,但极大降低爬取效率(规模一大就明显了)。

selenium更占用资源(cpu,内存,网络)

理由:打开一个/多个浏览器,浏览器里还有n个窗口.....

下面不多说,进入正题

前置

本体直接pip安装pip install selenium

驱动按需选择:

chrome (内核版本要对应,详看其中的notes.txt)

firefox (相信各位的英文实力)

IE (很少用吧)

下载好后把解压得到的驱动放到设置了环境变量的路径下就行了,如果你的python设置了环境变量,应该丢到python目录下就行了。

简单尝试

照例贴上文档,2.53旧版中文,想学更多就给我啃

选好浏览器就创建实例,之后的操作都在这个实例之上,并介绍一些有用的option,本文以Chrome为例。

from selenium import webdriver

#其他浏览器把Chrome换名就行

#option = webdriver.ChromeOptions()

#option.set_headless() 设置无头浏览器,就是隐藏界面后台运行

driver = webdriver.Chrome() #创建driver实例

#driver = webdriver.Chrome(chrome_options=option) 创建实例并载入option

url = '**********'

driver.get(url)

#driver.maximize_window() 最大化窗口

#driver.set_window_size(width,height) 设置窗口大小

print(driver.page_source) #打印网页源码

driver.quit() # 关闭浏览器

对付低级的动态网页(ajax较少)就是这么简单,基本不用考虑动态问题,徒手撸动态的人表示羡慕。然而更多时候并不像这样简单,直接套用的话很容易导致源码所见非所得,而且很多爬虫并没有简单到拿个源码就走的程度,它还要交互,模拟点击滚动等等。所以还请往下看,不要看到这就投入实战啦

定位

selenium提供多种方法对元素进行定位,返回WebElement对象,而上面提到的driver就相当于最大的WebElement对象

#以下都是单次定位,返回第一个定位到的。如果想多次定位,给element加个s就行,返回的是符合元素的列表

element = driver.find_element_by_id() # 通过标签的id定位,接收id属性值

driver.find_element_by_name() # 通过标签的name定位,接收name属性值

driver.find_element_by_xpath() # 通过xpath定位,接收xpath表达式

driver.find_element_by_link_text() # 通过标签的完全文本定位,接收完整的文本

driver.find_element_by_partial_link_text() # 通过标签的部分文本定位,接收部分文本

driver.find_element_by_tag_name() # 通过标签名定位,接收标签名

driver.find_element_by_class_name() # 通过标签的class定位,接收class属性值

driver.find_element_by_css_selector() # 通过css选择器定位,接收其语法

#返回的WebElement对象可以继续往下定位

xpath和css就不展开讲了,能实现精确定位,一定要学其中一个,不知道的小伙伴们上网自学吧,不难

除了上面这些公有的方法,还有2个私有的方法来帮助页面对象的定位。 这两个方法就是 find_element 和 find_elements,需要导入By类辅助,接收一个By类属性及其对应语法/值

from selenium.webdriver.common.by import By

driver.find_element(By.XPATH,'//a[text()="dark"]')

driver.find_elements(By.XPATH,'//a[text()="dark"]')

'''By类有以下属性

ID = "id"

XPATH = "xpath"

LINK_TEXT = "link text"

PARTIAL_LINK_TEXT = "partial link text"

NAME = "name"

TAG_NAME = "tag_name"

CLASS_NAME = "class name"

CSS_SELECTOR = "css selector"

'''

frame切换

很多人在用selenium会遇到所见非所得,或者定位页面元素的时候会定位不到的问题,这种情况很有可能是frame在搞鬼,必须切换到相应frame中再进行定位。如果遇到以上问题,第一时间F12看下你所要的信息是否在frame标签里面。

frame标签有frameset、frame、iframe三种,frameset跟其他普通标签没有区别,不会影响到正常的定位,而frame与iframe对selenium定位而言是一样的。

selenium提供了4种方法定位iframe并切换进去:

#对于.....

driver.switch_to_frame(0) # 用frame的index来定位,第一个是0,以此类推

driver.switch_to_frame("frame1") # 用id来定位

driver.switch_to_frame("dark") # 用name来定位

driver.switch_to_frame(driver.find_element_by_tag_name("iframe")) # 用WebElement对象来定位

通常通过id和name就能实现,无此属性时可以通过WebElement对象,即用find_element系列方法所取得的对象来定位。如果你确定每个目标frame都是固定第几个,那也可以用index定位

切到frame中之后,就不能继续操作主文档的元素了,这时如果想操作主文档内容,则需切回主文档。

driver.switch_to_default_content()

嵌套frame的切换

如果frame里包着frame而你要的frame是后者,那么需要一层一层切换进去,切换方法四选一

driver.switch_to_frame("frame1")

driver.switch_to_frame("frame2")

如果想回去上一个父frame,用driver.switch_to.parent_frame()

window 切换

有时候点开一个链接就会弹出一个新窗口,如果要对其操作就要切换过去,方法和frame的切换差不多,但只接收window_handle(相当于窗口的名字)来进行切换。driver.switch_to_window("windowName")

切换前最好保存之前的handle和所有的handles以便于来回切换。

current_window = driver.current_window_handle # 获取当前窗口handle name

all_windows = driver.window_handles # 获取所有窗口handle name

# 如果window不是当前window,则切换到该window,即切换到新窗口

for window in all_windows:

if window != current_window:

driver.switch_to_window(window)

#....

driver.switch_to_window(current_window) # 返回之前的窗口

driver.close() # 窗口的关闭用close()

页面交互

常用的页面交互有点击,输入文本等。交互的原则是先定位,后交互,比如你F12找到了某个文本框或某个可点击项的标签,那就先定位到那,再用以下的交互方法

from selenium.webdriver.common.keys import Keys

# 首先定位到某个文本框或某个可点击项(如超链接,按钮),

element = driver.find_element_by_xpath('//a[text()="dark"]')

element.send_keys("some text") # 往文本框输入文本

#element.send_keys("some text", Keys.ARROW_DOWN) 可以使用 Keys 类来模拟输入方向键

element.clear() # 清空文本框

#element.click() 如果此元素可点击,可用click()方法

要注意的一点是,不是定位到就必定能交互,有时候目标会被网页弹出来的东西覆盖,导致无法交互,所以要确保页面干净无覆盖

上下拉滚动

selenium可以执行js,下拉滚动可以通过此实现,因此就算不懂js也可以记一些有用的js代码

#driver.execute_script('js_str')

driver.execute_script('window.scrollTo(0,10000)') # 移动到指定坐标

driver.execute_script('window.scrollBy(0,10000)') # 相对当前坐标移动

driver.execute_script('window.scrollTo(0, document.body.scrollHeight)') # 相对当前坐标移动

等待

现在不少web都都有使用ajax技术,即异步加载,有时候你要的东西都还没加载到你就去定位了,就会抛出异常。为了避免此等血淋淋的惨状,必须要待其加载一段时间后再进行后面的操作。这里付一张不等待就获取page_source的后果

bVbeeiQ?w=1112&h=109

最粗暴的方法就是使用time.sleep(),这很笨,因为你还要设置合适的时间,而不同网站加载的速度有异,容易造成时间的浪费。所以最好还是使用selenium提供的两种等待方法

显式Wiats

显式Wiats允许你设置一个加载时间的上限和一个条件,每隔0.5s就判断一下所设条件,条件成立就继续执行下面的代码,如果过了时间上限还是没有成立,默认抛出NoSuchElementException 异常。这种相对智能的等待方法能最大化地节省时间,应该优先选择使用

selenium提供了多种expected_conditions(EC)来设置条件,但是要注意有定位时EC的方法接收的是定位信息的元组(locator_tuple)而不是两个参数,正确用法如EC.presence_of_element_located((By.ID,"dark"))

这个条件检测是否有id='dark'的元素

selenium提供的EC有以下方法,意思如其名,这里注释一些易搞错的,选择使用

title_is(str)

title_contains(str)

presence_of_element_located(locator_tuple)

visibility_of_element_located(locator_tuple) # 判断某个元素是否可见

visibility_of(WebElement) # 同上,传参不同

presence_of_all_elements_located(locator_tuple)

text_to_be_present_in_element(str) # 判断某个元素中的text是否包含了指定字符串

text_to_be_present_in_element_value(str) # 判断某个元素中的value属性是否包含了预期的字符串

frame_to_be_available_and_switch_to_it

invisibility_of_element_located(locator_tuple)

element_to_be_clickable(locator_tuple)

staleness_of(WebElement) # 等待某个元素从的移除

element_to_be_selected(WebElement)

element_located_to_be_selected(locator_tuple)

element_selection_state_to_be(WebElement)

element_located_selection_state_to_be(locator_tuple)

alert_is_present() # 判断页面上是否存在alert

使用上通常搭配try语句

from selenium.webdriver.common.by import By

from selenium.webdriver.support.ui import WebDriverWait # 导入显式等待

from selenium.webdriver.support import expected_conditions as EC # 导入EC

from selenium.common.exceptions import NoSuchElementException

# WebDriverWait(driver,time).until(EC) 显式waits

try:

element = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID,"myDynamicElement")))

except NoSuchElementException:

#.....

finally:

driver.quit()

隐式等待

隐式等待是在尝试定位某个元素的时候,如果没能成功,就等待固定长度的时间,默认0秒。一旦设置了隐式等待时间,它的作用范围就是Webdriver对象实例的整个生命周期。driver.implicitly_wait(10)

最后补充

这是用selenium几分钟弄出来的网易云音乐单曲评论爬虫,而且还模拟了评论翻页,还截了图。没提取信息,提取的时候可以用BeautifulSoup或正则提取,

from selenium import webdriver

import time

from selenium.common.exceptions import NoSuchElementException, TimeoutException

from selenium.webdriver.support import expected_conditions as EC

from selenium.webdriver.common.by import By

from selenium.webdriver.support.ui import WebDriverWait

driver = webdriver.Chrome()

driver.maximize_window()

driver.get("http://music.163.com/#/song?id=31877470")

driver.switch_to_frame("contentFrame")

time.sleep(5)

driver.execute_script('window.scrollTo(0, document.body.scrollHeight)')

driver.save_screenshot('E:/python3/gg.png') # 截图

b = driver.find_element_by_xpath("//a[starts-with(@class,'zbtn znxt')]")

b.click()

try:

WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH,"//a[@data-type='reply']")))

print(driver.page_source)

except NoSuchElementException:

print('OMG')

finally:

driver.quit()

短短二十行就能做到这种程度(而且不少还是import的),足以见得selenium强大。如果要手动分析,你还要分析js加密算法,写上n倍的代码。两者相比起来selenium真的很吸引人,简直是懒人救星。大家权衡利弊按需选择吧

python爬取js动态网页_Python 从零开始爬虫(八)——动态爬取解决方案 之 selenium相关推荐

  1. python多线程爬虫 爬取多个网页_python多线程爬虫爬取顶点小说内容(BeautifulSoup+urllib)...

    思路 之前写过python爬取起点中文网小说,多线程则是先把爬取的章节链接存到一个列表里,然后写一个函数get_text每次调用这个函数就传一个章节链接,那么就需要调用n次该函数来获取n章的内容,所以 ...

  2. python爬取网易云音乐_Python 从零开始爬虫(七)——实战:网易云音乐评论爬取(附加密算法)...

    前言 某宝评论区已经成功爬取了,jd的也是差不多的方法,说实话也没什么好玩的,我是看上它们分析简单,又没加密才拿来试手的.如果真的要看些有趣的评论的话,我会选择网易云音乐,里面汇聚了哲学家,小说家,s ...

  3. python 爬虫动态网页的区别_Python开发爬虫之动态网页抓取篇:爬取博客评论数据——通过Selenium模拟浏览器抓取...

    区别于上篇动态网页抓取,这里介绍另一种方法,即使用浏览器渲染引擎.直接用浏览器在显示网页时解析 HTML.应用 CSS 样式并执行 JavaScript 的语句. 这个方法在爬虫过程中会打开一个浏览器 ...

  4. python动态页面元素爬取_Python开发爬虫之动态网页抓取篇:爬取博客评论数据——通过浏览器审查元素解析真实网页地址...

    由于主流网站都使用JavaScript展示网页内容,和前面简单抓取静态网页不同的是,在使用JavaScript时,很多内容并不会出现在HTML源代码中,而是在HTML源码位置放上一段JavaScrip ...

  5. python爬取动态网页_python爬取动态网页数据,详解

    原理:动态网页,即用js代码实现动态加载数据,就是可以根据用户的行为,自动访问服务器请求数据,重点就是:请求数据,那么怎么用python获取这个数据了? 浏览器请求数据方式:浏览器向服务器的api(例 ...

  6. python实现监控电脑打开网页_Python轻松实现动态网页爬虫(附详细源码)

    AJAX动态加载网页 一 什么是动态网页 J哥一向注重理论与实践相结合,知其然也要知其所以然,才能以不变应万变. 所谓的动态网页,是指跟静态网页相对的一种网页编程技术.静态网页,随着html代码的生成 ...

  7. python爬虫(八、爬取图片社的小姐姐图片并下载)

    爬取网页 Ⅰ.先抓取下这个网页,套模板就好了\color{Red}Ⅰ.先抓取下这个网页,套模板就好了Ⅰ.先抓取下这个网页,套模板就好了 def ask(url):head = {"User- ...

  8. python读取excel送到网页_python怎么读取excel!怎么用python将excel数据写入网页中

    怎么用python将excel数据写入网页中 # 装 xlrd-0.9.2 xlutils-1.7.1 这两个模 from xlwt import Workbook, Formula import x ...

  9. python手机远程控制电脑访问网页_Python 实战系列-微信或网页远程控制电脑

    Python 实战系列-微信或网页远程控制电脑 本系列课程为Python实战系列课程:使用微信控制电脑,使用Python的Web框架Flask搭建网页, 并使用网页控制电脑:使用wxPython编写图 ...

最新文章

  1. 同一个Spring-AOP的坑,我一天踩了两次,深坑啊
  2. 阿里P8成长路线!我的头条面试经历分享,吊打面试官系列!
  3. 从getmemery()函数看内存管理、函数传参等一系列问题
  4. RPC与Apache Thift
  5. js for foreach 快慢_JS之 编码小技巧
  6. WinAPI: GetNextWindow - 获取指定窗口Z上或Z下的窗口的句柄
  7. 完美数的算法设计(C语言)
  8. k8s基本概念及使用
  9. # gazebo 仿真
  10. Tableau学习摘录总结①(层次、聚合度和颗粒度层次、聚合度和颗粒度,字段(离散和连续),小建议)
  11. 弥散阴影html,超赞!一份简单易上手的青春弥散阴影修炼手册
  12. 常见的标识符命名风格
  13. 点云3d检测SA-SSD
  14. uni-app里的拓展组件uni ui与UI框架uView UI的Popup 弹出层的区别!
  15. 企业应用系统集成的一般解决方案
  16. 很棒的一篇职业规划文章(2)
  17. 光耦合器的输入电路及重要参数
  18. 网络炸飞机 v1.20 官方
  19. nodejs安装时遇到的问题
  20. sscom5.13.1串口调试助手百度云下载免费

热门文章

  1. linux losetup命令,losetup命令_Linux losetup 命令用法详解:设定与控制循环(loop)设备...
  2. 桥本有菜java,深入浅出Extjs4.1.1(ExtJS组件、ExtJS对Ajax支持、ExtJS布局)配在线选课系统实战...
  3. php图片中不显示文字内容,水印效果 只有图片,文字不显示
  4. mac 无法启动linux系统安装,苹果官方技术文档显示新款Mac Mini不能安装Linux系统...
  5. 判断数组中某个元素除自身外是否和其他数据不同_18 张图带你彻底认识这些数据结构...
  6. 3-3:类与对象中篇——默认成员函数之构造函数和析构函数
  7. Thrift 编译链接的时候出问题
  8. 剑指 Offer 32 - II. 从上到下打印二叉树 II
  9. zip2john工具爆破zip文件
  10. Python字典类型内部做判断赋值