浅谈python爬虫使用Selenium模拟浏览器行为


Posted in Python onFebruary 23, 2018

前几天有位微信读者问我一个爬虫的问题,就是在爬去百度贴吧首页的热门动态下面的图片的时候,爬取的图片总是爬取不完整,比首页看到的少。原因他也大概分析了下,就是后面的图片是动态加载的。他的问题就是这部分动态加载的图片该怎么爬取到。

分析

他的代码比较简单,主要有以下的步骤:使用BeautifulSoup库,打开百度贴吧的首页地址,再解析得到id为new_list标签底下的img标签,最后将img标签的图片保存下来。

headers = {
 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'
}

data=requests.get("https://tieba.baidu.com/index.html",headers=headers)
html=BeautifulSoup(data.text,'lxml')

前面提到过,有部分图片是动态加载的,那么首先我们得弄清楚,这部分图片是怎么动态加载的。在浏览器中打开百度贴吧的首页,可以明显的看到,在往下滚动滚动条的时候,当滚动到底部的时候,滚动条缩短了,并向上移动了一段距离。这个现象也正是有DOM元素动态的添加到了html文档的一个表现。动态加载数据无非就是ajax请求,而ajax本质上就是XMLHttpRequest请求(简称xhr)。在谷歌浏览器中,我们可以通过开发者工具的network面板来监测xhr请求。

刚打开首页时的xhr请求,这里的请求都和要爬取的图片无关。

浅谈python爬虫使用Selenium模拟浏览器行为

滚动条向下第1次滚动到底部,这里请求的是第20-40条热门动态,包含要爬取图片。

浅谈python爬虫使用Selenium模拟浏览器行为

滚动条向下第2次滚动到底部,这里请求的是第40-60条热门动态,包含要爬取图片。并且返回的的has_more:false表明没有跟多数据了。

浅谈python爬虫使用Selenium模拟浏览器行为

滚动条向下第3次滚动到底部,再无xhr请求。

解决方案

根据上面的分析,我们已经明白,单纯使用BeautifulSoup进行爬虫的时候,只能爬取到1-20条热门动态里面的图片。为了爬取到完整的热门动态里面的图片,我们则需要模拟浏览器的滚动条滚动,让网页去触发xhr请求更多的热门动态。

在python中,如果需要模拟浏览器的行为,可以使用selenium库。selenium库是一个自动化测试框架,可以用来模拟测试浏览器的各种行为,这里我们使用它来模拟浏览器打开百度贴吧的首页,并模拟滚动条向下滚动到底部的操作。

安装

pip install selenium

下载浏览器驱动

火狐浏览器驱动,其下载地址是:https://github.com/mozilla/geckodriver/releases

谷歌浏览器驱动,其下载地址是:http://chromedriver.storage.googleapis.com/index.html?path=2.33/

opera浏览器驱动,其下载地址是:https://github.com/operasoftware/operachromiumdriver/releases

对照自己电脑安装的浏览器和对应的版本,分别从上面的地址下载驱动文件,也可以从我的github项目中统一下载以上几个驱动(地址:https://github.com/Sesshoumaru/attachments/tree/master/Selenium%20WebDriver)。下载解压后,将所在的目录添加系统的环境变量中。当然你也可以将下载下来的驱动放到python安装目录的lib目录中,因为它本身已经存在于环境变量(我就是这么干的)。

浅谈python爬虫使用Selenium模拟浏览器行为

使用python代码模拟浏览器行为

要使用selenium先需要定义一个具体browser对象,这里就定义的时候就看你电脑安装的具体浏览器和安装的哪个浏览器的驱动。这里以火狐浏览器为例:

from selenium import webdriver
browser = webdriver.Firefox()

再模拟打开贴吧首页:

browser.get(https://tieba.baidu.com/index.html)

再模拟滚动条滚动到底部

for i in range(1, 5):
 browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')
 time.sleep(1)

最后再使用BeautifulSoup,解析图片标签:

html = BeautifulSoup(browser.page_source, "lxml")
imgs = html.select("#new_list li img")

几个注意点

必须安装浏览器和浏览器驱动,并且浏览器和浏览器驱动要配到

即如果使用谷歌浏览器模拟网页行为,则需要下载谷歌浏览器驱动;
如果使用火狐浏览器模拟网页行为,则需要下载火狐浏览器驱动

浏览器驱动所在的目录要在环境变量中,或者定义浏览器browser的时候指定驱动的路径

selenium更多用法

查找元素

from selenium import webdriver

browser = webdriver.Firefox()
browser.get("https://tieba.baidu.com/index.html")

new_list = browser.find_element_by_id('new_list')
user_name = browser.find_element_by_name ('user_name')
active = browser.find_element_by_class_name ('active')
p = browser.find_element_by_tag_name ('p')

# find_element_by_name 通过name查找单个元素
# find_element_by_xpath 通过xpath查找单个元素
# find_element_by_link_text 通过链接查找单个元素
# find_element_by_partial_link_text 通过部分链接查找单个元素
# find_element_by_tag_name 通过标签名称查找单个元素
# find_element_by_class_name 通过类名查找单个元素
# find_element_by_css_selector 通过css选择武器查找单个元素
# find_elements_by_name 通过name查找多个元素
# find_elements_by_xpath 通过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 通过css选择武器查找多个元素

获取元素信息

btn_more = browser.find_element_by_id('btn_more')
print(btn_more.get_attribute('class')) # 获取属性
print(btn_more.get_attribute('href')) # 获取属性
print(btn_more.text) # 获取文本值

元素交互操作

btn_more = browser.find_element_by_id('btn_more')
btn_more.click() # 模拟点击,可以模拟点击加载更多

input_search = browser.find_element(By.ID,'q')
input_search.clear() # 清空输入

执行JavaScript

# 执行JavaScript脚本
browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')
browser.execute_script('alert("To Bottom")')

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
编写同时兼容Python2.x与Python3.x版本的代码的几个示例
Mar 30 Python
详解Python中DOM方法的动态性
Apr 11 Python
Python实现选择排序
Jun 04 Python
python实现发送邮件功能
Jul 22 Python
PyQt5每天必学之QSplitter实现窗口分隔
Apr 19 Python
Python之列表的插入&替换修改方法
Jun 28 Python
在python中对变量判断是否为None的三种方法总结
Jan 23 Python
python的range和linspace使用详解
Nov 27 Python
tensorflow保持每次训练结果一致的简单实现
Feb 17 Python
Django修改app名称和数据表迁移方案实现
Sep 17 Python
python判断字符串以什么结尾的实例方法
Sep 18 Python
Python实现迪杰斯特拉算法并生成最短路径的示例代码
Dec 01 Python
python kmeans聚类简单介绍和实现代码
Feb 23 #Python
python MysqlDb模块安装及其使用详解
Feb 23 #Python
Python实现k-means算法
Feb 23 #Python
python语言中with as的用法使用详解
Feb 23 #Python
python实现定时自动备份文件到其他主机的实例代码
Feb 23 #Python
Python机器学习算法之k均值聚类(k-means)
Feb 23 #Python
python3调用R的示例代码
Feb 23 #Python
You might like
利用PHP生成静态HTML文档的原理
2012/10/29 PHP
Session的工作机制详解和安全性问题(PHP实例讲解)
2014/04/10 PHP
php的mail函数发送UTF-8编码中文邮件时标题乱码的解决办法
2015/10/20 PHP
thinkPHP实现的联动菜单功能详解
2017/05/05 PHP
PHP使用星号替代用户名手机和邮箱的实现代码
2018/02/07 PHP
PHP创建XML接口示例
2019/07/04 PHP
由prototype_1.3.1进入javascript殿堂-类的初探
2006/11/06 Javascript
JavaScipt中的Math.ceil() 、Math.floor() 、Math.round() 三个函数的理解
2010/04/29 Javascript
利用jQuery实现可以编辑的表格
2014/05/26 Javascript
让html页面不缓存js的实现方法
2014/10/31 Javascript
用JavaScript来美化HTML的select标签的下拉列表效果
2015/11/17 Javascript
ReactJs实现树形结构的数据显示的组件的示例
2017/08/18 Javascript
浅谈AngularJs 双向绑定原理(数据绑定机制)
2017/12/07 Javascript
详解vue+vuex+koa2开发环境搭建及示例开发
2018/01/22 Javascript
详解jQuery中的isPlainObject()使用方法
2018/02/27 jQuery
vue实现歌手列表字母排序下拉滚动条侧栏排序实时更新
2019/05/14 Javascript
原生js实现自定义消息提示框
2020/11/19 Javascript
[36:41]完美世界DOTA2联赛循环赛FTD vs Magma第一场 10月30日
2020/10/31 DOTA
对python中的乘法dot和对应分量相乘multiply详解
2018/11/14 Python
Python 私有化操作实例分析
2019/11/21 Python
python实现数字炸弹游戏程序
2020/07/17 Python
html5 Canvas绘制线条 closePath()实例代码
2012/05/10 HTML / CSS
加利福尼亚州威尼斯的女性奢侈品设计师服装和概念店:Mona Moore
2018/09/13 全球购物
销售人员自我评价
2014/02/01 职场文书
党的群众路线教育实践活动心得体会
2014/03/03 职场文书
学习雷锋精神心得体会范文
2014/03/12 职场文书
企业党建工作汇报材料
2014/08/19 职场文书
2014年党员自我评议(5篇)
2014/09/12 职场文书
客户经理岗位职责大全
2015/04/09 职场文书
2015年幼儿园中班下学期工作总结
2015/05/22 职场文书
2015入党自传格式范文
2015/06/26 职场文书
高一地理教学工作总结
2015/08/12 职场文书
九年级语文教学反思
2016/03/03 职场文书
Go语言基础函数基本用法及示例详解
2021/11/17 Golang
InterProcessMutex实现zookeeper分布式锁原理
2022/03/21 Java/Android
vue-treeselect的基本用法以及解决点击无法出现拉下菜单
2022/04/30 Vue.js