动态页面抓取

目录

  • 动态页面抓取
    • 动态抓取的实例
    • 解析真实地址抓取
    • 通过Selenium模拟浏览器抓取
      • Selenium的安装与基本介绍
      • Selenium的实践案例
      • Selenium获取微博评论
      • Selenium的高级操作
      • Selenum爬虫实践:深圳短租数据
        • 项目实践
        • 自我实践题

动态页面抓取

前面爬取的页面都是静态页面,页面展示的内容都存储在HTML源代码中。

但是,现在主流的网站都使用JavaScript 展现网页内容,和静态网页不一样的是,使用JavaScript时,很多内容都不会出现在HTML源码中。

因此,我们需要用到爬取动态网页的两种技术:

  1. 通过浏览器审查元素解析真实网页地址
  2. 使用selenium模拟浏览器获取动态网页数据

动态抓取的实例

在爬取动态网页之前,我们需要先了解一种异步更新技术——AJAX(异步JavaScriptXML

它的价值在于通过在后台与服务器进行少量数据交换就可以使网页实现异步更新

这意味着可以在不更新加载整个网页的情况下对网页的某部分进行更新。

例如,我们在看微博评论时,网页不会将所有评论全部展现,而是我们往下滑一段就出现一段评论,这就用到了异步更新技术

比如:我们在异步加载网站中,我们看到的评论数据就是使用JavaScript加载的,不会出现在网页源代码中。
动态页面抓取_第1张图片
爬取动态网页的两种方法:

  1. 通过浏览器审查元素解析真实网页地址
  2. 使用selenium模拟浏览器获取动态网页数据

解析真实地址抓取

Chrome右键点击“检查”命令,单击页面中的“Network”选项,然后刷新网页。此时Network会显示浏览器从网页服务器中得到的所有文件,这个过程被称为“抓包

因为显示的文件太多,可以按crtl+F搜索想要的内容,会自动定位到该网页,例如我们根据网页的评论搜索定位
动态页面抓取_第2张图片
在headers中我们可以看到真实地址
动态页面抓取_第3张图片

import requests
import lxml.html
import json
url='https://api-zero.livere.com/v1/comments/list?callback=jQuery112404090822790751196_1609138618610&limit=10&repSeq=4272904&requestPath=%2Fv1%2Fcomments%2Flist&consumerSeq=1020&livereSeq=28583&smartloginSeq=5154&code=&_=1609138618612'
headers={
     'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Mobile Safari/537.36'}
r=requests.get(url,headers=headers)
print(r.text)
open('html.txt','w',encoding='utf-8').write(r.text)

运行代码我们发现我们想要的评论数据就包含在响应文件中
动态页面抓取_第4张图片
接下来就是从json数据中提取评论。上述结果比较杂乱,其实这些是json数据,我们可以使用json克时解析数据,从中提取想要的信息。

这时,我们发现这个网页数据不是正确的json格式
动态页面抓取_第5张图片
因为我们这里不涉及数据清洗内容,所以我们把错误的数据手动删除掉(第一行{ 前面的数据和结尾的);),删除完之后即为正确的json格式,即一个字典

import json
html=open('html.txt','r',encoding='utf-8').read()
json_data=json.loads(html)
comment_list=json_data['results']['parents']# json文件中的列表
for each in comment_list:
    print(each["content"])# 列表的content字段

动态页面抓取_第6张图片
这样,我们就把评论信息提取出来了

上面我们把第一页的评论爬取出来了,如果人工找每一页的真实地址会非常的麻烦,因此我们可以根据规律使用for循环爬取

我们可以发现第一页的真实地址是:https://api-zero.livere.com/v1/comments/list?callback=jQuery1124024945189329458972_1609143449063&limit=10&offset=1&repSeq=4272904&requestPath=%2Fv1%2Fcomments%2Flist&consumerSeq=1020&livereSeq=28583&smartloginSeq=5154&code=&_=1609143449073

第二页的真实地址是:https://api-zero.livere.com/v1/comments/list?callback=jQuery11240527837944980206_1609142567812&limit=10&offset=3&repSeq=4272904&requestPath=%2Fv1%2Fcomments%2Flist&consumerSeq=1020&livereSeq=28583&smartloginSeq=5154&code=&_=1609142567814

可以发现URL地址中有两个比较重要的变量,limit代表每一页评论数量的最大值,offset表示评论页

import requests
import lxml.html
import json
url='https://api-zero.livere.com/v1/comments/list?callback=jQuery112404090822790751196_1609138618610&limit=10&repSeq=4272904&requestPath=%2Fv1%2Fcomments%2Flist&consumerSeq=1020&livereSeq=28583&smartloginSeq=5154&code=&_=1609138618612'
headers={
     'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Mobile Safari/537.36'}
def single_page_comment(url,i):
    r=requests.get(url,headers=headers)
    print(r.text)
    open('html'+str(i)+'.txt','w',encoding='utf-8').write(r.text)
for i in range(5):
    link1='https://api-zero.livere.com/v1/comments/list?callback=jQuery11240527837944980206_1609142567812&limit=10&offset='
    link2='&repSeq=4272904&requestPath=%2Fv1%2Fcomments%2Flist&consumerSeq=1020&livereSeq=28583&smartloginSeq=5154&code=&_=1609142567814'
    url=link1+str(i+1)+link2
    single_page_comment(url,i+1)

# https://api-zero.livere.com/v1/comments/list?callback=jQuery1124024945189329458972_1609143449063&limit=10&offset=1&repSeq=4272904&requestPath=%2Fv1%2Fcomments%2Flist&consumerSeq=1020&livereSeq=28583&smartloginSeq=5154&code=&_=1609143449073
# https://api-zero.livere.com/v1/comments/list?callback=jQuery11240527837944980206_1609142567812&limit=10&offset=3&repSeq=4272904&requestPath=%2Fv1%2Fcomments%2Flist&consumerSeq=1020&livereSeq=28583&smartloginSeq=5154&code=&_=1609142567814

运行代码我们可以得到每一个评论页的源代码
动态页面抓取_第7张图片

通过Selenium模拟浏览器抓取

在之前的例子中,使用Chrome 的“检查”功能找到源地址十分容易,但是有一些网站非常复杂,如天猫产品评论,使用“检查”功能很难找到调用的网页地址。除此之外,有一些数据真实地址的URL也十分冗长和复杂,有些网站为了规避这些抓取会对地址进行加密,造成其中的一些变量让人摸不着头脑。

因此,这里介绍另一种方法,即使用浏览器渲染引擎。直接用浏览器在显示网页时解析HTML、应用CSS样式并执行JavaScript的语句。这个方法在爬虫过程中会打开一个浏览器加载该网页,自动操作浏览器浏览各个网页,顺便把数据抓下来。用- -句简单而通俗的话说,就是使用浏览器渲染方法将爬取动态网页变成爬取静态网页。

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

Selenium的安装与基本介绍

pip install selenium

下载ChromeDriver,根据自己的系统下载合适的版本,下载地址
动态页面抓取_第8张图片

from selenium import webdriver
driver=webdriver.Chrome()
driver.get('baidu.com')

使用代码模拟浏览器打开baidu.com,我们会发现会报错,这时因为在同文件文件路径中不存在ChromeDriver.exe文件

webdriver.Chrome()函数的参数为ChromeDriver.exe文件的路径,我们也可以把该文件复制到同路径下
动态页面抓取_第9张图片

Selenium的实践案例

正常情况下,右键点击“检查”,其中的Elements选择就是浏览器渲染的成的静态网页代码
动态页面抓取_第10张图片

Selenium获取微博评论

from selenium import webdriver
import time
driver=webdriver.Chrome()
driver.get('https://m.weibo.cn/detail/4467107636950632')
time.sleep(5)
html=driver.page_source
open('html.txt','w',encoding='utf-8').write(html)
print(html)
comment=driver.find_elements_by_xpath('//*[@id="app"]/div[1]/div/div[4]/div[2]/div/div/div/div/div/div[2]/div[1]/div/div/h3')
for each in comment:
    content=each.text
    print(content)

动态页面抓取_第11张图片

Selenium的高级操作

Selenium中常见的操作元素方法

  • Clear清除元素的内容
  • send_keys模拟按键输入
  • Click 点击元素
  • Submit 提交表单
    动态页面抓取_第12张图片
    Selenium的高级操作
  1. 控制CSS的加载
        from selenium import webdriver
 
        f = webdriver.FirefoxProfile()
        f.set_preference("permissions.default.stylesheet",2)
 
        driver = webdriver.Firefox(firefox_profile = f)
        driver.get('https://www.douban.com/')
  1. 控制图片文件的显示
          from selenium import webdriver
 
          f = webdriver.FirefoxProfile()
          f.set_preference("permissions.default.image",2)
 
          driver = webdriver.Firefox(firefox_profile = f)
          driver.get('https://www.douban.com/')
  1. 控制JavaScript的运行
           from selenium import webdriver
 
           f = webdriver.FirefoxProfile()
           f.set_preference("javascript.enabled",False)
 
           driver = webdriver.Firefox(firefox_profile = f)
           driver.get('https://www.douban.com/')

Selenum爬虫实践:深圳短租数据

项目实践

from selenium import webdriver
import time
url='https://www.airbnb.cn/s/%E6%B7%B1%E5%9C%B3%E5%B8%82/homes?refinement_paths%5B%5D=%2Fhomes&screen_size=large&checkin=2020-12-28&checkout=2020-12-29&host_promotion_type_ids%5B%5D=1&host_promotion_type_ids%5B%5D=8'
driver=webdriver.Chrome()
driver.get(url)
def driver_run(driver):
    time.sleep(5)
    comment=driver.find_elements_by_xpath('/html/body/div[3]/main/div/div/div/div[3]/div/div/section/div/div/div[2]/div/div/div[2]/div/div/div/div/div')
    for each in comment:
        name=each.find_element_by_xpath('div/div/div/div/div/div/div/div[2]/div/div/a/div[1]/div[2]/div/div').text
        print(name)
driver_run(driver)
for i in range(0,14):
    driver.find_element_by_xpath('//*[@id="site-content"]/div/div/div/div[3]/div/div/div/div[1]/div[1]/a[6]/svg/g/path').click()
    driver_run(driver)

自我实践题

爬取农贸市场所有商品名称与价格

from selenium import webdriver
import time
url='http://www.gznw.com/eportal/ui?pageId=595091'
driver=webdriver.Chrome()
driver.get(url)
def driver_run(driver):
    time.sleep(5)
    comment=driver.find_elements_by_xpath('//*[@id="5c96d136291949729295e25ea7e708b7"]/div[2]/div[2]/table/tbody/tr')
    for each in comment:
        name=each.find_element_by_xpath('td[2]').text
        price=each.find_element_by_xpath('td[4]').text
        print(name,"  ",price)
driver_run(driver)
for i in range(0,2014):
    driver.find_element_by_xpath('//*[@id="5c96d136291949729295e25ea7e708b7"]/div[2]/div[3]/table/tbody/tr/td/a[3]').click()
    driver_run(driver)

动态页面抓取_第13张图片

你可能感兴趣的:(python,爬虫)