python爬虫实战——微博点赞列表

python爬虫实战——微博点赞列表


有的数据明明在浏览器里可以看到,但使用 requests 库请求网页,却无法获得。

这种情况常见于滚动加载的页面

微博点赞列表 为例,尝试直接请求该网页:

import requests


url = "https://m.weibo.cn/detail/5056551155145232#attitude"

headers = {
    'Cookie': '自己的 cookie',
    'User-Agent': '自己的 user-agent'
}

resp = requests.get(url, headers=headers)  # 使用 get 请求获取网页
text = resp.content.decode('utf-8')        # 解码为文本

print(text)

输出的内容中,并未包含点赞用户。

页面结构里没有的数据,却出现在了浏览器显示中,因此想要正确地获取这些数据数据,就要先明白 数据是如何进入页面的


json文件获取

一般这类需要动态加载的数据,都是通过json文件发送到你的电脑上

在谷歌浏览器中,进入检查模式(右键 - 检查),选择网络(Network)栏目,然后刷新网页,可以看到网络栏目中出现了很多条目:

按照 类型 排序,其中类型为 xhr 的就是json文件。

尝试滚动页面,并观察类型为 xhr 文件的变化,可以看出,下图中的文件在逐渐增多:

因此,我们大胆猜测,{% emp 每次滚动页面时,新增的点赞数据都在这里面 %}。

为了验证这一猜想,我们随便选择一个文件,鼠标左键单击,查看它的信息:

可以看出,它是由 get 请求得到的,网址为:

https://m.weibo.cn/api/attitudes/show?id=5056551155145232&page=3

我们直接访问这一网址,看看其中的内容:

可以看出,点赞用户的数据确实出现在其中。

因此,我们只要 直接使用requests库的get方式请求这一网址,即可获得我们想要的点赞用户数据:

import requests


url = "https://m.weibo.cn/api/attitudes/show?id=5056551155145232&page=3"

# 请求头部分,可参考上图文件信息中的“请求标头”设计
headers = {
    'User-Agent': '你的 user-agnet'
    # “请求标头”中没有cookie,因此不必设置
}

resp = requests.get(url, headers=headers)  # 使用get方法请求网页
json_data = resp.json()

print(json_data)

至此,我们成功请求到了json文件,将其储存在电脑上。

import json

with open('page3.json', 'w') as f:
    json.dump(json_data, f, indent=4)
    # indent 是一个让 json 文件展示更加美观的参数

使用python解析json文件

json 文件可以理解为 字典和列表的嵌套,因此想要提取其中的数据,需要先借助大括号和方括号的位置,分析字典和列表的嵌套关系:

  • { 表示里面的内容是一个字典,使用访问字典数据的方式提取其中的数据,如 key-value 方法
  • [ 表示里面的内容是一个列表,使用访问列表数据的方式提取其中的数据,如索引方法

以我们刚刚获取的 json 文件为例:

{  // 最外层是一个字典
    "ok": 1,  // json_data['ok'] 是一个元素
    "msg": "...",  // json_data['msg'] 是一个元素
    "data": {  // json_data['data'] 是一个字典
        "max": 4295,  // json_data['data']['max'] 是一个元素
        "total_number": 214724,  // json_data['data']['total_number'] 是一个元素
        "data": [  // json_data['data']['data'] 是一个列表
            {  // json_data['data']['data'][0] 是一个字典
                "id": 5076463254504741,  // json_data['data']['data'][0]['id']
                "created_at": "09-08",
                "source": "Xiaomi 13",
                "user": {  // json_data['data']['data'][0]['user'] 是一个字典
                    "id": 6347472563,
                    "screen_name": "...",
                    "profile_image_url": "...",
                    "followers_count": "31",
                    "profile_url": "...",
                    "follow_me": false,
                    "verified": false,
                    "verified_type": -1,
                    ...
                }
            },

因此,如果我们想提取所有用户的 idverified_type 这两个字段,需要:

id_verified_dict = {}
for user_data in json_data['data']['data']:  # 遍历列表
    id_verified_dict[user_data['user']['id']] = user_data['user']['verified_type']

*附:verified_type 的含义

verified_type含义verified_type含义
-1普通用户6应用
0名人7团体、机构
1政府8待审企业
2企业200初级达人
3媒体220高级达人
4校园400已故 V 用户
5网站

其中,verified_type=0 为黄 v,其他为蓝 v。


遍历爬取微博的点赞信息

在爬取数据之前,我们先在浏览器里 手动查看一下,可以发现最多只能查看 50 个 json 文件,这些文件的链接存在规律:

https://m.weibo.cn/api/attitudes/show?id={博文id}&page={页面序号}

接下来,我们遍历地请求这些网站,并获取每个用户的 id用户名

import requests
import json
import random
import time


headers = {
    'User-Agent': '你的 user-agent'
}

def getdata_by_blogid(blogid=5056551155145232):

    id_username = {}

    # page 从 1 到 50 遍历
    for page in range(1, 51):
        
        # 生成 url
        url = "https://m.weibo.cn/api/attitudes/show?id={}&page={}".format(blogid, page)
        
        # 请求 json 网页
        resp = requests.get(url, headers)

        # 将请求到的内容转换为 json 格式
        json_data = resp.json()

        # 遍历当前 json 文件中的用户列表,提取 id 和 username
        for user_data in json_data['data']['data']:  # 遍历列表
            id_username[user_data['user']['id']] = user_data['user']['screen_name']
        
        sleep_time = random.uniform(1, 3)
        print("blogid={},page={} 请求成功,{} 秒后继续.".format(blogid, page, sleep_time))
        time.sleep(sleep_time)
    
    return id_username

id_username = getdata_by_blogid()

实际数据采集过程中,可能会遇到一些问题,如页面请求失败、json 文件中没有对应路径、当前博文点赞数量较少(不到 page=50 就结束了)等,因此需要对代码做出优化如下:

import requests
import json
import random
import time


headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36'
}

def getdata_by_blogid(blogid=5056551155145232):

    id_username = {}

    # page 从 1 到 50 遍历
    for page in range(1, 51):
        
        # 生成 url
        url = "https://m.weibo.cn/api/attitudes/show?id={}&page={}".format(blogid, page)
        
        # 请求 json 网页并判断是否请求成功
        resp = requests.get(url, headers)
        if resp.status_code != 200:
            page -= 1
            sleep_time = random.uniform(5, 10)
            print("blogid={},page={} 请求失败,{} 秒后重试.".format(blogid, page, sleep_time))
            time.sleep(sleep_time)
            continue

        # 将请求到的内容转换为 json 格式
        json_data = resp.json()

        # 表示当前点赞微博的点赞数据(可获取的部分)已经请求完毕
        if json_data['ok'] == 0:
            sleep_time = random.uniform(5, 10)
            print("blogid={},page={} 请求结束,{} 秒后继续.".format(blogid, page, sleep_time))
            time.sleep(sleep_time)
            break

        # 表示当前 page 的 json 文件虽然请求成功了,但里面不包含数据
        if json_data['ok'] != 1: 
            page -= 1
            sleep_time = random.uniform(5, 10)
            print("blogid={},page={} 请求失败,{} 秒后重试.".format(blogid, page, sleep_time))
            time.sleep(sleep_time)
            continue
        
        # 遍历当前 json 文件中的用户列表,提取 id 和 username
        for user_data in json_data['data']['data']:  # 遍历列表
            id_username[user_data['user']['id']] = user_data['user']['screen_name']
        
        sleep_time = random.uniform(1, 3)
        print("blogid={},page={} 请求成功,{} 秒后继续.".format(blogid, page, sleep_time))
        time.sleep(sleep_time)
    
    return id_username

id_username = getdata_by_blogid()


以上就是通过请求 json 文件获取数据的基本方法。

通过 json 进行数据采集,属于较为高级的数据采集方法,掌握这一方法已经可以满足大部分数据采集的需求。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值