赞
踩
先登录微博跳转到指定界面,在搜索框中输入你想要获取的数据,例如这里我输入pel
,可以看到查询数据的接口,滑到最后点击下一页可以发现参数page=2
,说明page
参数用做页面查询。
https://s.weibo.com/weibo?q=xxx&page=xxx # q是查询数据的参数,page页面参数
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 # 获取页面数据,以文本的形式返回
按F12或者右键选择检查,点击网络(network
)然后刷新页面,选中该文档界面查看请求头,获取到请求头中的cookie
和user-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就行了
}
点击评论会异步请求数据(XHR
),观察数据包可以找到请求评论数据的url,且发现不同请求的mid值不同。
https://s.weibo.com/Ajax_Comment/small # 评论接口
经过测试在发送请求评论数据时需要加上referer
和X-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' # 必须加上,不然会报请求方式出错
}
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
需要获取的数据为:作者名称,时间,发布的内容,评论
选择页面元素,先点击下图所示按钮
接着点击页面上要获取数据,例如下图点击发帖人的名字,这时可以定位到该元素在html所处位置。
通过观察html发现“作者名称,时间,发布的内容”这三个数据都在class=content
t的div
标签中。
点击元素(Elements)接着按ctrl+f
可以使用xpath语法进行测试匹配数据,这里先匹配该div标签
//div[@class="content"]
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']) # 请求评论接口,并返回处理后的数据
因为请求评论数据的请求参数mid值会发生变化,所以mid值可能是来区分不同的请求数据,为了抓取不同的评论数据。
在元素(Elements)搜索mid=
可在点赞按钮a标签的action-data属性中找到
利用xpath语法匹配到mid的值
mids = tree.xpath('//div[@class="card-act"]//li[3]/a/@action-data') # 匹配到每一个评论的mid值
构造请求参数
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(".", "")}' # 修改时间戳格式,不重要可随意修改
}
发送请求并解析返回评论数据
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
使用python库openpyxl先创建一个工作簿Workbook之后创建活页表,添加标题并写上爬取数据的列名。
from openpyxl import Workbook
wb = Workbook() # 创建一个工作簿
ws = wb.active # 获取活动工作表
ws.title = "微博信息" # 标题
ws.append(['名字', '时间', '内容', '评论']) # 列名
ws作为参数传递到parse_page_source方法中,将解析后的数据以列表或元素的形式添加到表中
ws.append([name, t.strip(), content.strip(), comment]) # 将数据插入到表中
最后保存数据为weibo.xlsx
wb.save('weibo.xlsx') # 保存爬取的数据
不要完全复制粘贴,把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() # 程序入口
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。