用户、话题、评论一网打尽,分享一个最强微博爬虫

实现的功能

微博向来是一个极好的吃瓜圣地,为了获取微博上行行色色的数据,微博相关的爬虫也是层出不穷,由于不管是运营者仍是数据分析从业者都或多或少须要微博数据,个人许多朋友也不例外,通过断断续续的努力,我完成了一个多是史上最强大的微博爬虫的编写。html

该爬虫的功能主要分为三部分,第一个主打功能是爬取指定用户的全部微博(能够经过热键 Ctrl + P 快速打开),这个用户能够按照昵称搜索,能够选择是否只抓取原创微博,以下图
在这里插入图片描述
爬取的微博内容保存在 csv 文件中,表头包括微博id、微博正文、图片url、发布位置、发布时间、发布工具和点赞数、评论数、转发数,其中图片url里面是全部微博图片的url以英文逗号间隔拼接起来的。
在这里插入图片描述
第二个主打功能是爬取指定话题下的全部微博,以下图
在这里插入图片描述
微博保存的 csv 格式大体和爬取用户微博格式相似。web

第三个主打功能就是爬取根据微博id爬取该微博下的全部评论详情,好比微博 id 为 IaYZIu0Ko 的全部评论为:
在这里插入图片描述
除了爬虫的业务逻辑,你们也能够在上面看到,有较为友好的操做界面,方便你们操做。正则表达式

技术路线

代码共计 1000 余行,不关心技术的同窗能够直接跳到文末获取程序连接。

爬虫部分主要是 经过 Chrome 分析微博页面上的接口,获取接口参数,使用 requests 库模拟请求,须要带上 cookies ,我这个爬虫的大头实际上是解析部分,我主要用了 lxml 库,须要解析的东西很是多,差很少 csv 中的每个字段都须要单独的代码块来解析。微信

爬虫实现的三个功能:按用户爬取、按话题爬取、爬取微博全部评论,我分别用了三个类来实现,WeiboUserScrapy、WeiboTopicScrapy、WeiboCommentScrapy,三个类都有一些能够复用的函数,可是为了减小类之间的耦合,以及方便打包,我没有复用,这样单独一个类拿出来也能跑,减小了依赖。cookie

再主要是界面模块的编写,我以前一直用 wxPython 编写界面,后来深刻学习了 pyqt5 这个库,因此这个爬虫的界面是用 pyqt5 来写的,这里主要用到了 ListView model-view模型、自定义信号及槽函数和一些常见组件的使用。多线程

爬虫比较耗时,而界面又不容许阻塞,因此必须采用多线程技术,使用自定义信号做为爬虫类和界面类之间沟通的桥梁,好比爬虫开始、结束都会向界面类发出相应的信号完成界面的更新。app

目前有个不完善的地方就是,后台任务除了进度框和打印,没有其余可视化查看的方法,并且各任务之间的调度只是简单的先到先服务,后续我会自定义调度器类,完成各类暂停、恢复、优先级处理等各类智能调度以及高级的可视化界面。svg

核心代码讲解

以 WeiboCommentScrapy 类为例,首先经过正则表达式获取评论总数,函数

res = requests.get('https://weibo.cn/comment/{}'.format(self.wid),headers=self.headers,verify=False)
commentNum = re.findall("评论\[.*?\]",res.text)[0]
commentNum = int(commentNum[3:len(commentNum)-1])

而后根据评论总数分页工具

pageNum = ceil(commentNum/10)

接着两层循环,外层遍历页数,内层遍历每一页的评论,最后对每个评论作解析

for page in range(pageNum):
	
	result = []

    res = requests.get('https://weibo.cn/comment/{}?page={}'.format(self.wid,page+1), headers=self.headers,verify=False)

    html = etree.HTML(res.text.encode('utf-8'))

    comments = html.xpath("/html/body/div[starts-with(@id,'C')]")

    print('第{}/{}页'.format(page+1,pageNum))

    for i in range(len(comments)):
		result.append(self.get_one_comment_struct(comments[i]))

    if page==0:
		self.write_to_csv(result,isHeader=True)
    else:
		self.write_to_csv(result,isHeader=False)
	# 休眠 1-5 秒,防止被封
    sleep(randint(1,5))

注意看内层循环,看上去每一页都是 10 条评论,实则否则,好比第一页有热门评论,会超过 10 条,最后一页可能没有 10 条,因此内层循环没有用 for i in range(10): 而是 for i in range(len(comments)):。内层循环还调用了一个函数 get_one_comment_struct(),其做用是根据 xpath 获得的每一条 comment 元素解析获得咱们想要的数据,其中又递归调用了几个自定义解析函数,好比解析获得的时间是诸如“xxx分钟前"、“刚刚”,咱们须要进一步作字符串处理获得具体时间戳。

因为本爬虫都是用 lxml 库采用 xpath 解析的,里面我遇到了许许多多的实用技巧,会在后续博客作详细展开。

获取使用

为了方便你们使用,我已经把程序打包成 exe ,脱离了 Python 环境运行,只须要在微信公众号后台回复 微博爬虫 便可得到,同时因为接口变化,我会按期升级程序,为防止失联可在后台回复 社群,加入微信粉丝团,便可及时获取程序更新。

微信公众号:月小水长
在这里插入图片描述