MENU

爬虫案例:Ajax数据爬取--爬取个人微博页

July 5, 2020 • 数据采集与数据分析(python)

先简单介绍下Ajax,全称Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。它并不是编程语言额,而是利用JavaScript在保证页面不被刷新,页面链接不改变的情况下与服务器交换数据并更新部分网页的一种技术。(可以理解为多个技术组合而成,包括JavaScript、DOM、CSS等)
Ajax使用简单的XMLHttpRequest对象发送请求,使用简单的JavaScript函数监视服务器响应。在服务器响应完成后,JavaScript通过DOM动态更新HTML页面。自始至终用户无需终端,感受连续的体验。

更详细的信息请查阅https://www.w3school.com.cn/ajax/index.asp。这里不再详细讲解,接下来介绍案例。

案例介绍
爬取并解析新浪微博的博主个人页面所有信息,本案例的爬取的林俊的个人页面 林俊杰

开始
Ajax分析

  • 查看请求与响应
    打开浏览器开发者工具,切换到Network选项卡,刷新页面可以发现有非常多的条目。第一响应页(第一条)知识框架并没有任何数据,除第一响应页还有很多CSS样式表。那么真实的数据在哪里呢?!

Ajax其实有特殊的请求类型:XMLHttpRequest(xhr)
在开发者工具中点击 XHR 过滤除XHR其他请求。接下来会得到一个 ‘getIndex?’开头的条目:

分析请求信息.png

可以看到请求头 :

{
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3756.400 QQBrowser/10.5.4039.400',
    'X-Requested-With':'XMLHttpRequest',
    'Referer':'https://m.weibo.cn/search?containerid=100103type%3D1%26q%3D%E6%9E%97%E4%BF%8A%E6%9D%B0'
}

请求的参数:

params = {
    'uid':'1195354434',
    't':'0',
    'containerid':'1076031195354434',
    'luicode':'10000011',
    'lfid':'100103type=1&q=林俊杰',
    'type':'uid',
    'value':'1195354434',
    'since_id':since_id

}

接下来分析响应,切换preview选项卡,观察响应内容,发现其实就是JSON格式数据。
响应分析.jpg
发现这里面包含了很多信息,比如点赞数(attitudes_count)、评论数(comments_count)、微博正文(text)、转发数、发布时间等等信息。
知道了Ajax技术原理和数据所在位置,接下来整理思路:
最终数据都在以

https://m.weibo.cn/api/container/getIndex?

为前缀的JSON格式的页面上,这样就可以使用requests获取网页数据然后解析成JSON格式,再由python标准库中提供的json库解析详细的细节。

源码如下:

import requests
from urllib.parse import urlencode
import json
from pyquery import PyQuery as pq


heads = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3756.400 QQBrowser/10.5.4039.400',
    'X-Requested-With':'XMLHttpRequest',
    'Referer':'https://m.weibo.cn/search?containerid=100103type%3D1%26q%3D%E6%9E%97%E4%BF%8A%E6%9D%B0'
}

since_id = None     //默认空值,其因为首页不需要since_id。再得到首页数据时,会自动提供下一页的since_id

def params_result(since_id):  //get请求参数,since_id时获取下一页的重要参数,由上一页的JSON中的‘cradlistinfo’标签得到
    params = {
        'uid': '1195354434',
        't': '0',
        'containerid': '1076031195354434',
        'luicode': '10000011',
        'lfid': '100103type=1&q=林俊杰',
        'type': 'uid',
        'value': '1195354434',
        'since_id': since_id
    }
    return params

base_url = 'https://m.weibo.cn/api/container/getIndex?'  

def get_page(param):    //获取XHR页面数据,并返回JSON格式
    url = base_url + urlencode(param)
    print(url)
    try:
        r = requests.get(url=url,headers=heads)
        if r.status_code == 200:
            return r.json()
    except requests.ConnectionError as e:
        print('Error',e.args)



def parse_json(json):   //从JSON标签中解析重要数据
    if json:
        junjies = json.get('data').get('cards')   

        for item in junjies:
            item = item.get('mblog')   
            message = {}
            message['id'] = item.get('id')  
            message['text'] = pq(item.get('text')).text()
            message['time'] = item.get('created_at')
            message['comments'] = item.get('comments_count')
            message['attitudes'] = item.get('attitudes_count')
            yield message

if __name__ == '__main__':
    i = 0
   # since_id = 4518250752448965
    while i < 6:   //用于测试,只爬取6页
        i = i +1
        param = params_result(since_id=since_id)
        print(param)
        json = get_page(param)
        since_id = json.get('data').get('cardlistInfo').get('since_id')   //*重要!获取下一页地址的参数since_id
        results = parse_json(json)
        for result in results:
            print(result)

最终爬取结果如下:
result.png

Last Modified: July 11, 2020