动态网页抓取(区别于上篇动态网页抓取,这里介绍另一种方法)
优采云 发布时间: 2021-11-24 06:06动态网页抓取(区别于上篇动态网页抓取,这里介绍另一种方法)
与之前的动态网页抓取不同,这里还有一种方法,就是使用浏览器渲染引擎。显示网页时直接使用浏览器解析HTML,应用CSS样式并执行JavaScript语句。
该方法会在抓取过程中打开浏览器加载网页,自动操作浏览器浏览各种网页,顺便抓取数据。通俗点讲,就是利用浏览器渲染的方式,把爬取的动态网页变成爬取的静态网页。
我们可以使用Python的Selenium库来模拟浏览器来完成爬取。Selenium 是一种用于 Web 应用程序测试的工具。Selenium 测试直接在浏览器中运行,浏览器自动按照脚本代码进行点击、输入、打开、验证等操作,就像真实用户在操作一样。
模拟浏览器通过 Selenium 爬行。最常用的是火狐,所以下面的解释也以火狐为例。运行前需要安装火狐浏览器。
以《Python Web Crawler:从入门到实践》一书作者的个人博客评论为例。网址:
运行以下代码时,一定要注意你的网络是否畅通。如果网络不好,浏览器无法正常打开网页及其评论数据,可能会导致抓取失败。
1)找到评论的HTML代码标签。使用Chrome打开文章页面,右击页面,打开“检查”选项。目标评论数据。这里的评论数据是浏览器渲染出来的数据位置,如图:
2)尝试获取评论数据。在原打开页面的代码数据上,我们可以使用如下代码获取第一条评论数据。在下面的代码中,driver.find_element_by_css_selector使用CSS选择器来查找元素,并找到class为'reply-content'的div元素;find_element_by_tag_name 搜索元素的标签,即查找注释中的 p 元素。最后输出p元素中的text text。
相关代码1:
from selenium import webdriver
from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
caps=webdriver.DesiredCapabilities().FIREFOX
caps["marionette"]=True
binary=FirefoxBinary(r'E:\软件安装目录\装机必备软件\Mozilla Firefox\firefox.exe') #把上述地址改成你电脑中Firefox程序的地址
driver=webdriver.Firefox(firefox_binary=binary,capabilities=caps)
driver.get("http://www.santostang.com/2017/03/02/hello-world/")
#page=driver.find_element_by_xpath(".//html")
driver.switch_to.frame(driver.find_element_by_css_selector("iframe[title='livere']"))
comment=driver.find_element_by_css_selector('div.reply-content-wrapper') #此处参数字段也可以是'div.reply-content',具体字段视具体网页div包含关系而定
content=comment.find_element_by_tag_name('p')
print(content.text)
#driver.page_source
输出:
在JS 里面也找不到https://api.gentie.163.com/products/ 哪位大神帮忙解答下。谢谢。
代码分析:
1)caps=webdriver.DesiredCapabilities().FIREFOX
可以看到,上面代码中的caps["marionette"]=True被注释掉了,代码还是可以正常运行的。
2)binary=FirefoxBinary(r'E:\软件安装目录\安装必备软件\Mozilla Firefox\firefox.exe')
3)driver=webdriver.Firefox(firefox_binary=binary,capabilities=caps)
构建 webdriver 类。
您还可以构建其他类型的 webdriver 类。
4)driver.get("")
5)driver.switch_to.frame(driver.find_element_by_css_selector("iframe[title='livere']"))
6)comment=driver.find_element_by_css_selector('div.reply-content-wrapper')
7)content=comment.find_element_by_tag_name('p')
更多代码含义和使用规则请参考官网API和导航:
8)关于driver.switch_to.frame(driver.find_element_by_css_selector("iframe[title='livere']"))中的frame定位和标题内容。
可以在代码中添加 driver.page_source 并注释掉 driver.switch_to.frame(driver.find_element_by_css_selector("iframe[title='livere']"))。可以在输出内容中找到(如果输出比较乱,很难找到相关内容,可以复制粘贴成文本文件,用Notepad++打开,软件有前面对应的显示功能和背面标签):
(这里只截取相关内容的结尾)
如果使用driver.switch_to.frame(driver.find_element_by_css_selector("iframe[title='livere']")),然后使用driver.page_source进行相关输出,就会发现上面没有iframe标签,证明我们有了框架 分析完成后,就可以进行相关定位得到元素了。
上面我们只得到了一条评论,如果你想得到所有的评论,使用循环来得到所有的评论。
相关代码2:
from selenium import webdriver
from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
caps=webdriver.DesiredCapabilities().FIREFOX
caps["marionette"]=True
binary=FirefoxBinary(r'E:\软件安装目录\装机必备软件\Mozilla Firefox\firefox.exe')
driver=webdriver.Firefox(firefox_binary=binary,capabilities=caps)
driver.get("http://www.santostang.com/2017/03/02/hello-world/")
#page=driver.find_element_by_xpath(".//html")
driver.switch_to.frame(driver.find_element_by_css_selector("iframe[title='livere']"))
comments=driver.find_elements_by_css_selector('div.reply-content')
for eachcomment in comments:
content=eachcomment.find_element_by_tag_name('p')
print(content.text)
#driver.page_source
输出:
在JS 里面也找不到https://api.gentie.163.com/products/ 哪位大神帮忙解答下。谢谢。
@先生姓张 原来要按照这里的操作才行。。。
在JS 里面也找不到https://api.gentie.163.com/products/ 哪位大神帮忙解答下。谢谢。
@先生姓张 这是网易云上面的一个连接地址,那个服务器都关闭了
在JS 里面也找不到https://api.gentie.163.com/products/ 哪位大神帮忙解答下。谢谢。
测试
为什么我用代码打开的文章只有两条评论,本来是有46条的,有大神知道怎么回事吗?
菜鸟一只,求学习群
lalala1
我来试一试
我来试一试
应该点JS,然后看里面的Preview或者Response,里面响应的是Ajax的内容,然后如果去爬网站的评论的话,点开js那个请求后点Headers -->在General里面拷贝 RequestURL 就可以了
注意代码2中,代码1中的comment=driver.find_element_by_css_selector('div.reply-content-wrapper')改为comments=driver.find_elements_by_css_selector('div.reply-content')
添加的元素
以上获得的所有评论数据均属于网页的正常入口。网页渲染完成后,所有获得的评论都没有点击“查看更多”加载尚未渲染的评论。