python实现微博个人主页的信息爬取

微博个人主页的信息爬取

闲话少说,先进入分析过程。
因为相对而言移动端的界面会比较好爬取,所以今天我们爬取移动端微博的页面,如下:
python实现微博个人主页的信息爬取_第1张图片
这里是前后端分离异步加载的数据,所以我们去抓包工具下寻找对应的接口地址:
python实现微博个人主页的信息爬取_第2张图片
很明显可以看到crads下对应了多条数据,而其中的mblog下存放着对应微博的相关数据:
python实现微博个人主页的信息爬取_第3张图片
不要着急现在就去解析界面数据,先去看看下一页的加载,怎样去请求下一条数据:
python实现微博个人主页的信息爬取_第4张图片
对比看到多出了一个since_id的数据,发现这个数据的来源是上一条json数据中的:
python实现微博个人主页的信息爬取_第5张图片
到这里我们的分析就结束了,接下来进行代码的编写。

import requests
from urllib.parse import urlencode
import random

# 个人微博内容循环爬取,基于强大的requests库

# 伪装头
headers = {
     
    "Host": "m.weibo.cn",
    "Referer": "https://m.weibo.cn/u/6816603335",
    "user-agent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, "
                  "like Gecko) Chrome/87.0.4280.88 Mobile Safari/537.36 Edg/87.0.664.66 ",
    "X-Requested-With": "XMXLHttpRequest"
}
# 接口链接模板
base_url = 'https://m.weibo.cn/api/container/getIndex?'
# ip代理池
proxy_pool = [{
     'HTTP': '27.206.178.75:9000'}, {
     'HTTP': '175.42.122.226:9999'}, {
     'HTTP': '175.42.158.31:9999'},
              {
     'HTTP': '175.44.109.38:9999'}, {
     'HTTP': '42.238.91.46:9999'}, {
     'HTTP': '175.42.158.146:9999'},
              {
     'HTTP': '123.160.69.171:9999'}, {
     'HTTP': '115.221.240.115:9999'}, {
     'HTTP': '183.166.110.5:9999'},
              {
     'HTTP': '125.121.123.115:8888'}, {
     'HTTP': '117.64.237.222:1133'}, {
     'HTTP': '182.87.39.163:9000'},
              {
     'HTTP': '120.79.184.148:8118'}, {
     'HTTP': '122.234.24.178:9000'}, {
     'HTTP': '175.42.158.74:9999'}]
# 预定义字典
weibo = {
     }

接下来我们进行函数的编写,封装两个函数,用来请求数据 和 解析数据。
请求参数如下:
python实现微博个人主页的信息爬取_第6张图片

# 对链接的请求函数
def get_page(since_id=None):
    # 爬取用户的参数
    params = {
     
        'uid': '2946150412',
        'luicode': '10000011',
        'lfid': '231093_-_selffollowed',
        'type': 'uid',
        'value': '2946150412',
        'containerid': '1076032946150412',
        'since_id': since_id
    }
    # url拼接
    url = base_url + urlencode(params)
    try:
        # 对拼接字符串进行访问
        response = requests.get(url=url, headers=headers, proxies=random.choice(proxy_pool))
        if response.status_code == 200:
            # 响应成功后,将返回的json数据解析,返回json和其中的since_id
            # since_id是为了循环爬取下一条
            json = response.json()
            next_since_id = json.get('data').get('cardlistInfo').get('since_id')
            return json, next_since_id
    except requests.ConnectionError as e:
        # 失败 控制台抛出异常
        print("错误:", e.args)

上面的函数会返回一个json对象和since_id的数据,json对象用来解析微博的对应信息,since_id为我们的下次爬取提供参数

# 解析传回来的json
def parse_page(json):
    # 部分card属性下,存放着mblog,即是对应的微博内容
    cards = json.get('data').get('cards')
    for card in cards:
        mblog = card.get('mblog')
        # 循环遍历,获取对应的每一条数据,有mblog属性再解析
        if mblog:
            # 发布微博的来源
            weibo['source'] = mblog['source']
            # 创建时间
            weibo['created_at'] = mblog['created_at']
            # 文本内容
            weibo['raw_text'] = mblog['raw_text']
            # 图片
            weibo['original_pic'] = mblog.get('original_pic')
            # 图床的相关处理
            pics = []
            p = mblog.get('pics')
            if p:
                for pic in p:
                    pics.append(pic['url'])
                weibo['pics'] = ' , '.join(pics)
                # 提交
            yield weibo

最后封装一个函数调用上面的两个方法,并做到循环请求和解析的效果。

# 调用封装好的函数并进行持久化存储
def domain():
    global return_data
    # 循环请求数据接口,200次已经很多了,获取不到对应的since_id时,程序会报错停止
    for i in range(200):
    # 由于第一页没有since_id参数,这里特殊处理
        if i == 0:
            print("正在爬取第{}页....".format(i + 1))
            # 第一个接口没有since_id参数 传值为空
            return_data = get_page()
            # 下面的语句参照else中的注释
            results = parse_page(return_data[0])
            for res in results:
                img = res.get('original_pic')
                pics = res.get('pics')
                if img is None:
                    img = "无"
                if pics is None:
                    pics = "无"
                with open('test.txt', 'a', encoding='utf8') as file:
                    file.write('时间:' + res['created_at'] + '\n' + '来源:' + res['source'] + '\n'
                               + '内容:' + res['raw_text'] + '\n' + '附图链接地址:' + img + '\n'
                               + '图床:' + pics + '\n' + '\n')
        else:
            print("正在爬取第{}页....".format(i + 1))
            # 传入返回的第二个值since_id
            return_data = get_page(return_data[1])
            # 传入解析的第一个值json对象
            results = parse_page(return_data[0])
            # 遍历提交的结果
            for res in results:
                # 对照片和图床进行非空判断
                img = res.get('original_pic')
                pics = res.get('pics')
                if img is None:
                    img = "无"
                if pics is None:
                    pics = "无"
                # 持久化存储用文本实现
                with open('test.txt', 'a', encoding='utf8') as file:
                    file.write('时间:' + res['created_at'] + '\n' + '来源:' + res['source'] + '\n'
                               + '内容:' + res['raw_text'] + '\n' + '附图链接地址:' + img + '\n'
                               + '图床:' + pics + '\n' + '\n')

运行结果如下:
python实现微博个人主页的信息爬取_第7张图片
最后看一下我们的结果文件:
python实现微博个人主页的信息爬取_第8张图片
python实现微博个人主页的信息爬取_第9张图片
可以看到最早的2015年的微博也获取到了,对应的图片链接也是可以访问没有问题的。

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