模拟Ajax请求爬取网站动态信息

  有时候我们在用requests抓取页面的时候,得到的结果可能和在浏览器中看到的不一样:在浏览器中可以看到正常显示的页面数据,但是使用requests得到的结果中并没有。这是因为requests获取的都是原始的HTML文档,而浏览器中的页面则是经过JavaScript处理数据后生成的结果,这些数据的来源有多种,可能是通过Ajax加载的,可能是包含在HTML文档中的,也可能是经过JavaScript 和特定算法计算后生成的。

  对于第一种情况,数据加载是一种异步加载方式,原始的页面最初不会包含某些数据,原始页面加载完后,会再向服务器请求某个接口获取数据,然后数据才被处理从而呈现到网页上,这其实就是发送了一个ajax请求。

  照Web发展的趋势来看,这种形式的页面会越来越多。网页的原始HTML文档不会包含任何数据,数据都是通过Ajax统一加载后再呈现出来的,这样在Web开发上可以做到前后端分离,而且降低服务器直接渲染页面带来的压力。

  所以如果遇到这样的页面,直接利用requests等库来抓取原始页面,是无法获取到有效数据的,这时需要分析网页后台向接口发送的Ajax请求,

发送Ajax请求到网页更新的这个过程可以简单分为以下3步:

  • 通过javascript的XMLHttpRequest对象向服务器发送请求
  • 将服务器返回的数据进行解析和转化
  • 将能够使用的数据通过javascript的DOM操作应用到原始html页面上

  模拟ajax请求进行爬取首先就是要获取网页向服务器发送的xhr请求,这是针对ajax特定的请求方式,根据ajax请求的网址分析请求的有哪些数据,在游览器开发者工具中,还可以清晰的看到ajax请求后服务器返回的json数据,javascript就是根据类似这样的数据包来重新渲染页面的。

通过游览器的开发者工具进行分析:
在这里插入图片描述

服务器返回的json数据:
在这里插入图片描述

下面是一个从微博(也存在ajax请求)页面爬取信息的爬虫例子:

from urllib.parse import urlencode
import requests
base_url = 'https://m.weibo.cn/api/container/getIndex?'

headers = {
    'Host': 'm.weibo.cn',
    'Referer': 'https://m.weibo.cn/u/2830678474',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
    'X-Requested-With': 'XMLHttpRequest'
}

# 通过requests模拟ajax请求发送获取微博页面的某一分页
def get_page(page):
    params = {
        'type': 'uid',
        'value': '2830678474',
        'containerid': '1076032830678474',
        'page': page
    }
    url = base_url + urlencode(params)
    try:
        response = requests.get(url, headers=headers)
        if response.status_code == 200:
            return response.json()
    except requests.ConnectionError as e:
        print('Error', e.args)

from pyquery import PyQuery as pq

# 提取返回json数据中的信息
def parse_page(json):
    if json:
        items = json.get('data').get('cards')
        print(type(items))
        for item in items:
            item = item.get('mblog')
            if(item):
                weibo = {}
                # 可以直接通过给空字典赋值来添加其内的元素
                weibo['id'] = item.get('id')
                weibo['text'] = pq(item.get('text')).text()
                weibo['attitudes'] = item.get('attitudes_count')
                weibo['comments'] = item.get('comments_count')
                weibo['reposts'] = item.get('reposts_count')
                yield weibo

if __name__ == '__main__':
    for page in range(1, 10):
        json = get_page(page)
        results = parse_page(json)
        for result in results:
            with open('weibo.txt', 'wb') as file:
                file.write(result)
            # print(result)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值