写在前面
一直以为微博的东西比较好搞,没想到还是有点坑。新浪把评论的模块保存在一个json字典里,真的是够了。。。前20页可以轻易爬取,21页以后需要获取前一页最后一个评论的ID以及已经展示的评论总数。
包和全局变量
#时间管理带师
import time
#网页请求
import requests
#解析网页
from bs4 import BeautifulSoup as bs
#统计已经展示的评论数量
num = 0
#请自行登录新浪获取cookie
cookie = {}
#请求头
headers = {
'sec-fetch-dest':'empty',
'sec-fetch-mode':'cors',
'sec-fetch-site':'same-origin',
'referer':'https://weibo.com/2803301701/J6iwvbK2m?filter=hot&root_comment_id=0&type=comment',
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36',
'x-requested-with':'XMLHttpRequest'
}
#爬取前20页的参数,目前缺少page参数
params_1 = {
"ajwvr":6,
"id":"4515011752798578",
"from":"singleWeiBo",
}
#爬取21页以后的参数,目前缺少两个参数
params_2 = {
"ajwvr":6,
"id":"4515011752798578",
"root_comment_max_id_type":"1",
"root_comment_ext_param":"",
"filter":"hot",
"filter_tips_before":"1",
"from":"singleWeiBo",
}
#评论接口
url = 'https://weibo.com/aj/v6/comment/big'
几个函数
#获取毫秒级时间戳
def get_time():
cur_time = int(round(time.time() * 1000))
return cur_time
#获取包含评论的网页标签
def get_html(params):
#请求网页
res = requests.get(url = url,headers = headers,cookies = cookie,params = params)
#从json中获取数据
html = res.json()['data']['html']
#解析文本
bf = bs(html,'lxml')
#找到当前页全部评论并以列表形式返回
WB_texts = bf.find_all('div',class_ = 'list_li S_line1 clearfix')
return WB_texts
#获取20页之前的评论
def parse_before(page,params):
#num作为全局变量
global num
#补充参数,页数和当前时间
params['page'] = page
params['__rnd'] = get_time()
#获取评论列表
WB_texts = get_html(params)
#逐条写入并统计评论数量
for WB_text in WB_texts:
#因为class属性为WB_text的div有两个,所以用try-except来筛选
try:
f.write(WB_text.find('div',class_ = 'WB_text').text.strip().split(':')[1] + '\n')
num += 1
except:
pass
print('第{}页抓取完毕'.format(page))
#抓取21页之后的评论
def parse_after(page):
#num全局变量
global num
#补充参数,第21页暂不需要root_comment_max_id和sum_comment_number
params_2['page'] = page
params_2['__rnd'] = get_time()
#获取评论列表
WB_texts = get_html(params_2)
#逐条写入并统计评论数量
for WB_text in WB_texts:
try:
f.write(WB_text.find('div',class_ = 'WB_text').text.strip().split(':')[1] + '\n')
num += 1
except:
pass
#尝试设置root_comment_max_id,可能会因爬取速度过快而出现异常,而且会导致后续一直异常
try:
#获取最后一条评论的comment_id
max_id = int(WB_texts[-1].get('comment_id'))
#补充参数
params_2['root_comment_max_id'] = max_id
print('第{}页抓取完毕'.format(page))
except:
#异常原因是当前页根本没有抓到评论
if len(WB_texts) == 0:
print('第{}页抓取失败'.format(page))
pass
#补充评论数量参数
params_2['sum_comment_number'] = num
入口函数
if __name__ == '__main__':
#创建文本文件
f = open('weibo.txt','wt',encoding = 'utf-8')
#抓取120页的评论
for page in range(1,121):
#前20页以第一种方式获取,后面的以另一种方式
if page <= 20:
parse_before(page,params=params_1)
else:
parse_after(page)
#暂停一秒
time.sleep(1)
#关闭文件
f.close()
写在后面
只是粗略写了一下,好多代码可以复用。。懒得优化了。