当前位置:   article > 正文

微博信息爬取_微博爬取

微博爬取

微博信息爬取

爬取准备

获取查询接口:

登录微博跳转到指定界面,在搜索框中输入你想要获取的数据,例如这里我输入pel,可以看到查询数据的接口,滑到最后点击下一页可以发现参数page=2,说明page参数用做页面查询。

https://s.weibo.com/weibo?q=xxx&page=xxx	# q是查询数据的参数,page页面参数
  • 1

在这里插入图片描述

query, page = input("请输入要查询的数据和爬取的页数:").split(',')  # 在输入数据时以逗号分隔
for i in range(0, int(page)):
    url = f'https://s.weibo.com/weibo?q={query}&page={i}'	# 翻页
    res = get_page_source(url, headers).text	# 获取页面数据,以文本的形式返回
  • 1
  • 2
  • 3
  • 4
获取cookie和user-agent

按F12或者右键选择检查,点击网络(network)然后刷新页面,选中该文档界面查看请求头,获取到请求头中的cookieuser-agent
在这里插入图片描述
在这里插入图片描述

headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0',
    'cookie': 'xxx自己的cookie',	# 填自己的cookie就行了
}
  • 1
  • 2
  • 3
  • 4
'
运行
获取评论接口

点击评论会异步请求数据(XHR),观察数据包可以找到请求评论数据的url,且发现不同请求的mid值不同。

https://s.weibo.com/Ajax_Comment/small	# 评论接口
  • 1

在这里插入图片描述

获取头部关键字段

经过测试在发送请求评论数据时需要加上refererX-Requested-With字段

com_headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0',
    'cookie': 'xxx',	# 填自己的cookie
    'referer': f'https://s.weibo.com/weibo?q={query}',	# query是输入要查询的数据
    'x-requested-with': 'XMLHttpRequest'  # 必须加上,不然会报请求方式出错
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

页面爬取和解析

爬取页面数据的方法
def get_page_source(url, headers, **kwargs):
    try:
        if kwargs:
            res = requests.get(url, headers=headers, params=kwargs['params'])  # 带参数的请求
        else:
            res = requests.get(url, headers=headers)
        res.raise_for_status()  # 如果请求返回了不成功的HTTP状态码(如4xx或5xx),则会抛出一个HTTPError异常
        return res
    except Exception as e:
        return e
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
'
运行
利用xpath匹配相关数据

需要获取的数据为:作者名称,时间,发布的内容,评论

选择页面元素,先点击下图所示按钮

在这里插入图片描述

接着点击页面上要获取数据,例如下图点击发帖人的名字,这时可以定位到该元素在html所处位置。

在这里插入图片描述

通过观察html发现“作者名称,时间,发布的内容”这三个数据都在class=contentt的div标签中。

在这里插入图片描述

点击元素(Elements)接着按ctrl+f可以使用xpath语法进行测试匹配数据,这里先匹配该div标签

//div[@class="content"]
  • 1

在这里插入图片描述

xpath匹配数据不过多讲解,可自行学习,这里给出匹配数据的python代码

tree = etree.HTML(res)	# res是请求到的页面源码,利用lxml库中etree.HTML方法解析html数据
contents = tree.xpath('//div[@class="content"]')  # 利用xpath语法匹配到微博内容
for i in range(0, len(contents)):
    name = contents[i].xpath('./div[@class="info"]/div[2]/a/text()')[0]	# 作者名称
    t = contents[i].xpath('./div[@class="from"]/a[1]/text()')[0]	# 发布时间
    content = "".join(contents[i].xpath('./p[1]/text()'))	# 发布内容
    if contents[i].xpath('./p[2]'):
    	content = "".join(contents[i].xpath('./p[2]/text()'))
	comment = parse_comments(kwargs['com_url'], mids[i][4:], kwargs['params'],
                         kwargs['com_headers'])  # 请求评论接口,并返回处理后的数据
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
获取评论数据
  1. 因为请求评论数据的请求参数mid值会发生变化,所以mid值可能是来区分不同的请求数据,为了抓取不同的评论数据。

  2. 在元素(Elements)搜索mid=可在点赞按钮a标签的action-data属性中找到

在这里插入图片描述

  1. 利用xpath语法匹配到mid的值

    mids = tree.xpath('//div[@class="card-act"]//li[3]/a/@action-data')  # 匹配到每一个评论的mid值
    
    • 1
  2. 构造请求参数

    params = {
        'act': 'list',
        'mid': '5023800819190171',  # 这里随意写,后面会被改成真正要请求数据的mid值
        'uid': 'xxx',	# 填自己的请求数据包中的uid
        'smartFlag': 'false',
        'smartCardComment': '',
        'isMain': 'true',
        'suda-data': 'key%3Dtblog_search_weibo%26value%3Dweibo_h_1_p_p',
        'pageid': 'weibo',
        '_t': '0',
        '__rnd': f'{str(time.time())[:-4].replace(".", "")}'  # 修改时间戳格式,不重要可随意修改
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  3. 发送请求并解析返回评论数据

    def parse_comments(url, mid, params, headers):
        params['mid'] = mid  # 把参数中的mid值进行替换
        res = get_page_source(url, headers, params=params)	# headers为构造好的
        html = res.json()['data']['html']
        tree = etree.HTML(html)
        comment = "".join(tree.xpath('//div[@class="txt"]/text()'))  # 匹配到返回的评论
        c = re.sub('[: ]', '', comment).replace('\n\n', '')  # 利用正则表达书去掉多余的字符
        return c
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    '
    运行

保存数据为excel格式

使用python库openpyxl先创建一个工作簿Workbook之后创建活页表,添加标题并写上爬取数据的列名。

from openpyxl import Workbook
wb = Workbook()  # 创建一个工作簿
ws = wb.active  # 获取活动工作表
ws.title = "微博信息"  # 标题
ws.append(['名字', '时间', '内容', '评论'])  # 列名
  • 1
  • 2
  • 3
  • 4
  • 5

ws作为参数传递到parse_page_source方法中,将解析后的数据以列表或元素的形式添加到表中

ws.append([name, t.strip(), content.strip(), comment])  # 将数据插入到表中
  • 1

最后保存数据为weibo.xlsx

wb.save('weibo.xlsx')  # 保存爬取的数据
  • 1

程序运行和结果显示

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

源码

不要完全复制粘贴,把cookie和uid换成自己的

import time
import re
import requests
from lxml import etree
from openpyxl import Workbook
from urllib.parse import quote


def get_page_source(url, headers, **kwargs):
    try:
        if kwargs:
            res = requests.get(url, headers=headers, params=kwargs['params'])  # 带参数的请求
            res.encoding = res.apparent_encoding
        else:
            res = requests.get(url, headers=headers)
        res.raise_for_status()  # 如果请求返回了不成功的HTTP状态码(如4xx或5xx),则会抛出一个HTTPError异常
        return res
    except Exception as e:
        return e


def parse_page_source(res, ws, **kwargs):
    tree = etree.HTML(res)
    contents = tree.xpath('//div[@class="content"]')  # 利用xpath语法匹配到微博内容
    mids = tree.xpath('//div[@class="card-act"]//li[3]/a/@action-data')  # 匹配到每一个评论的mid值
    for i in range(0, len(contents)):
        if contents[i].xpath('./div[@class="info"]') is []:
            continue  # 如果内容中没有
        name = contents[i].xpath('./div[@class="info"]/div[2]/a/text()')[0]
        t = contents[i].xpath('./div[@class="from"]/a[1]/text()')[0]
        content = "".join(contents[i].xpath('./p[1]/text()'))
        if contents[i].xpath('./p[2]'):
            content = "".join(contents[i].xpath('./p[2]/text()'))
        comment = parse_comments(kwargs['com_url'], mids[i][4:], kwargs['params'],
                                 kwargs['com_headers'])  # 请求评论接口,并返回处理后的数据
        print(name)
        print(t.strip())
        print(content.strip())
        print(comment)
        ws.append([name, t.strip(), content.strip(), comment])  # 将数据插入到表中


def parse_comments(url, mid, params, headers):
    params['mid'] = mid  # 把参数中的mid值进行替换
    res = get_page_source(url, headers, params=params)
    html = res.json()['data']['html']
    tree = etree.HTML(html)
    comment = "".join(tree.xpath('//div[@class="txt"]/text()'))  # 匹配到返回的评论
    c = re.sub('[: ]', '', comment).replace('\n\n', '')  # 利用正则表达书去掉多余的字符
    return c


def main():
    query, page = input("请输入要查询的数据和爬取的页数:").split(',')  # 在输入数据时以逗号分隔
    query = quote(query)  # 将查询数据进行url编码,不然返回的数据会报编码错误
    # 发送初始查询数据请求,要在请求头加上cookie
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0',
        'cookie': 'xxx',	# 写自己的cookie
    }
    # 如果请求获取评论数据,需要添加下面的头部字段
    com_headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0',
        'cookie': 'xxx', # 写自己的cookie
        'referer': f'https://s.weibo.com/weibo?q={query}',
        'x-requested-with': 'XMLHttpRequest'  # 必须加上,不然会报请求方式出错
    }
    com_url = 'https://s.weibo.com/Ajax_Comment/small'  # 评论接口
    params = {
        'act': 'list',
        'mid': '5023800819190171',  # 关键在这个,不同评论的mid不同,获取到不同的mid值再去请求数据
        'uid': 'xxx',  # uid写自己的!!!
        'smartFlag': 'false',
        'smartCardComment': '',
        'isMain': 'true',
        'suda-data': 'key%3Dtblog_search_weibo%26value%3Dweibo_h_1_p_p',
        'pageid': 'weibo',
        '_t': '0',
        '__rnd': f'{str(time.time())[:-4].replace(".", "")}'  # 修改时间戳格式
    }
    wb = Workbook()  # 创建一个工作簿
    ws = wb.active  # 获取活动工作表
    ws.title = "微博信息"  # 标题
    ws.append(['名字', '时间', '内容', '评论'])  # 列名
    for i in range(0, int(page)):
        url = f'https://s.weibo.com/weibo?q={query}&page={i}'  # 将查询的数据和爬取的页数插到查询url
        res = get_page_source(url, headers).text
        parse_page_source(res, ws, com_url=com_url, params=params, com_headers=com_headers)  # 解析数据
        wb.save('weibo.xlsx')  # 保存爬取的数据


if __name__ == '__main__':
    main()  # 程序入口
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93

总结:

  1. 请求目标数据一定要加上一些关键的http头部信息,并使用自己的cookie和uid
  2. xapth匹配数据的语法没有详细的讲解,读者可自行学习相关语法
  3. 有一些细节问题需要注意如:对查询数据进行url编码防止输入中文时返回数据编码错误,利用python字符串处理方法和正则表达式对数据中的控制字符或一些特殊字符进行处理,使数据格式更美观。
  4. 这里只是爬取前9个评论,后续会出爬取所有评论的方法和python代码。
  5. 对于微博信息爬取,本文也只提供一些思路和方法,虽然我尽力确保本文内容的准确性,但难免会有疏漏之处,请各位谅解指正,如果大家有更好的想法欢迎留言讨论。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/841379
推荐阅读
相关标签
  

闽ICP备14008679号