评论爬取当然也要范围,比如说某一条微博下面的所有评论。这里我挑选一篇汶川10周年的微博,bid
为GgdfidjFm
进行爬取。
随便点一篇微博进行评论,会发现链接是这样的。
https://weibo.cn/comment/GgdfidjFm?uid=2803301701&rl=0#cmtfrm
而点“下页”会变成这样。
https://weibo.cn/comment/GgdfidjFm?uid=2803301701&rl=0&page=2
其中的#cmtfrm
应该是锚链到comment form,不用管它。
而rl=0
就是普通的评论列表,热门列表是rl=1
。这两个列表并没有什么区别,都是50页左右就爬不到了,可以结合使用。
uid=2803301701
是人民日报的用户id。这些好像都是可以不带的。
所以只要遍历https://weibo.cn/comment/GgdfidjFm?page=1~n
就可以了。
于此同时,评论一共44281页。
同样的,我们构造一个名为get_comments
的函数。值得注意的是,第一个参数不再是'rmrb'
这样的name
,而是'GgdfidjFm'
这样的微博bid
。
def get_comments(bid,page,start=1):
print(bid,page,start)
get_comments('GgdfidjFm',44281)
然后,针对每一页,我们构造一个函数叫做get_comments_from_page
,并与get_comments
进行拼接。
def get_comments(bid,page,start=1):
for current_page in range(start,page+1):
print(current_page)
url = 'https://weibo.cn/comment/%s?page=%d' % (bid,current_page)
get_comments_from_page(url,bid) # 这里建议把bid也传进去,便于从各种微博的评论里筛选出某条微博的评论
请求的发送和页面的解析是和微博爬取时一样的。
import requests
from bs4 import BeautifulSoup
import re
headers = {'cookie':'XXX'}
def get_comments_from_page(url,bid):
r = requests.get(url,headers=headers)
r.encoding = 'utf-8'
soup = BeautifulSoup(r.text, 'html5lib')
comments = soup.select("div[id^='C_']") # 不一样的是,这里是'C_'开头的div
for comment in comments:
comment_manage(comment,bid)
get_comments_from_page('https://weibo.cn/comment/GgdfidjFm?page=1')
清理的时候稍微有点不一样。多了一个bid
,微博的bid
对应评论的cid
,转发和评论都没有了。
def comment_manage(comment,bid):
temp = {
'bid': bid, # 这里传了bid用于识别是哪篇微博下的评论
'cid': comment['id'].split("_")[1],
'content': comment.find("span",class_="ctt").text,
'attitudes_count': re.split(r"[\[\]]",comment.find("a",string=re.compile(r"^赞\[")).text)[1],
'created_at': comment.find("span",class_="ct").text
}
save_comment(temp)
储存的时候也只是collection和唯一识别符不一样。
import pymongo
myclient = pymongo.MongoClient("mongodb://XXX:[email protected]:27017/")
mydb = myclient["weibo_DB"]
def save_comment(temp):
mycol = mydb["weibo_comments"] # 存放到评论的集合collection
flag = mycol.find_one({"cid":temp['cid']}) # 用cid保证评论不重复
if flag:
print('已存在')
else:
mycol.insert_one(temp)
至此,评论爬取也会了,不过好像突破不了50页的限制,只能获取300-500条,就算是人工访问,结果也是一样的,这个待处理。