zoukankan      html  css  js  c++  java
  • Python开发爬虫之动态网页抓取篇:爬取博客评论数据——通过Selenium模拟浏览器抓取

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

    这个方法在爬虫过程中会打开一个浏览器加载该网页,自动操作浏览器浏览各个网页,顺便把数据抓下来。用一句简单而通俗的话说,就是使用浏览器渲染方法将爬取动态网页变成爬取静态网页。

    我们可以用 Python 的 Selenium 库模拟浏览器完成抓取。Selenium 是一个用于Web 应用程序测试的工具。Selenium 测试直接运行在浏览器中,浏览器自动按照脚本代码做出单击、输入、打开、验证等操作,就像真正的用户在操作一样。

    通过Selenium模拟浏览器抓取。最常用 的是 Firefox,因此下面的讲解也以 Firefox 为例,在运行之前需要安装 Firefox 浏 览器。

    以爬取《Python 网络爬虫:从入门到实践》一书作者的个人博客评论为例。网址:http://www.santostang.com/2017/03/02/hello-world/

    在运行下列代码时,一定要留意自己网络是否畅通,如果网络不好造成浏览器不能正常打开网页及其评论数据,就可能造成爬取失败。

    1)找到评论的HTML代码标签。使用Chrome打开该文章页面,右键点击页面,打开“检查”选项。定位到评论数据。此处定位到的评论数据即是浏览器渲染后的数据位置,如图:

    2)尝试获取一条评论数据。在原来打开页面的代码数据上,我们可以使用以下代码,获取第一条评论数据。在下面代码中,driver.find_element_by_css_selector是用CSS选择器查找元素,找到class为’reply-content’的div元素;find_element_by_tag_name则是通过元素的tag去寻找,意思是找到comment中的p元素。最后,再输出p元素中的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 Firefoxfirefox.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 Firefoxfirefox.exe')

     3)driver=webdriver.Firefox(firefox_binary=binary,capabilities=caps)

     构建webdriver类。

    还可以构建别的类型的webdriver类。

    4)driver.get("http://www.santostang.com/2017/03/02/hello-world/")

    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和Navigating:http://selenium-python.readthedocs.io/index.html

     8)关于driver.switch_to.frame(driver.find_element_by_css_selector("iframe[title='livere']"))中的框架定位及title内容。

    可在代码中加入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 Firefoxfirefox.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')

    elements加了s

     

    以上获取的全部评论数据均属于正常进入该网页,等该网页渲染完获取的全部评论,并未进行点击“查看更多”来加载目前还未渲染的评论。

    下面介绍一种能够爬取到所有评论,包括点击完“查看更多”加载的目前还未渲染的评论。

    相关代码:

    from selenium import webdriver
    from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
    import time
    
    caps=webdriver.DesiredCapabilities().FIREFOX
    caps["marionette"]=True
    binary=FirefoxBinary(r'E:软件安装目录装机必备软件Mozilla Firefoxfirefox.exe')
    driver=webdriver.Firefox(firefox_binary=binary,capabilities=caps)
    driver.get("http://www.santostang.com/2017/03/02/hello-world/")
    driver.switch_to.frame(driver.find_element_by_css_selector("iframe[title='livere']"))
    
    time.sleep(60)
    for i in range(0,10):
        try:
            load_more=driver.find_element_by_css_selector('div.more-wrapper')
            load_more.click()
        except:
            pass
        time.sleep(5)
    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)

    代码解析:

    1)time.sleep(60)

    延时60秒执行以下代码。

    2)load_more=driver.find_element_by_css_selector('div.more-wrapper')中的参数字符串

    打开目标网页,等目标网页整体渲染完之后,右键评论区的“查看更多”。

    3)load_more.click()

    模拟点击“查看更多”按钮,进行完整显示所有评论。

    4)之所以在代码中两次使用延时函数,是因为不同网络状况和不同机器环境下可能在打开网页以及点击“查看更多”按钮后不能马上显示评论,所以代码需要等一等,等到页面完全渲染后,再进行评论区数据的收集工作。

    因此各延时函数的延时时间长短可视具体情况灵活设置。

     输出结果:

    在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 就可以了
    现在死在了4.2节上,页面评论是有的,但是XHR里没有东西啊,这是什么情况?有解决的大神吗?
    @骨犬 JS
    为何静态网页抓取不了?
    
    奇怪了,我按照书上的方法来操作,XHR也是空的啊
    @易君召 我的也是空的
    你解决问题了吗
    @思い亦深 看JS不是XHR
    XHR没有显示任何东西啊。奇怪。
    找到原因了
    caps["marionette"] = True
    作者可以解释一下这句话是干什么的吗
    @A cat named GitHub 改成 caps["marionette"] = False 可以运行。 目前还没吃透代码,先用着试试
    我用的是 pycham IDE,按照作者的写法写的,怎么不行
    @A cat named GitHub 找到原因了
    caps["marionette"] = True
    作者可以解释一下这句话是干什么的吗
    对火狐版本有要求吗
    @花晨 我的也是提示火狐版本不匹配,你解决了吗
    @A cat named GitHub 重装了geckodriver
    改成caps["marionette"] = "Windows"
    总之就好了
    4.3.1 打开Hello World,代码用的作者的,火狐地址我也设置了,为啥运行没反应
    from selenium import webdriver
    from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
    
    caps = webdriver.DesiredCapabilities().FIREFOX
    caps["marionette"] = False
    binary = FirefoxBinary(r'C:Program FilesMozilla Firefoxfirefox.exe')
    #把上述地址改成你电脑中Firefox程序的地址
    driver = webdriver.Firefox(firefox_binary=binary, capabilities=caps)
    driver.get("http://www.santostang.com/2017/03/02/hello-world/")
    我是番茄
    为什么刷新没有XHR数据,评论明明加载出来了
    为什么刷新没有XHR数据,评论明明加载出来了
    @萌萌哒的小叽叽丶 书里错误很多,留个qq吧
    为什么刷新没有XHR数据,评论明明加载出来了
    第21条测试评论
    第20条测试评论
    第19条测试评论
    第18条测试评论
    第17条测试评论
    第16条测试评论
    第15条测试评论
    第14条测试评论
    第13条测试评论
    第12条测试评论
    第11条测试评论
    第10条测试评论
    第9条测试评论
    第8条测试评论
    第7条测试评论
    第6条测试评论
    第5条测试评论
    第4条测试评论
    第3条测试评论
    第二条测试评论
    第一条测试评论

    参考书目:唐松,来自《Python 网络爬虫:从入门到实践》

     参考书目作者关于本部分的介绍:http://www.santostang.com/2017/09/25/4-3-%E9%80%9A%E8%BF%87-selenium-%E6%A8%A1%E6%8B%9F%E6%B5%8F%E8%A7%88%E5%99%A8%E6%8A%93%E5%8F%96/

  • 相关阅读:
    DateTimePicker常用格式类型
    自定义TreeNode
    memoのPython环境配置
    关于隐式积分方程的一些问题
    Position Based Dynamics【译】
    memoのMac折腾记录
    20210425 助教一周小结(第十二周)
    20210328 助教一周小结(第八周)
    20210307 助教一周小结(第五周)
    20210404 助教一周小结(第九周)
  • 原文地址:https://www.cnblogs.com/dudududu/p/8835977.html
Copyright © 2011-2022 走看看