前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >用户、话题、评论一网打尽,分享一个最强微博爬虫

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

作者头像
月小水长
发布2019-10-14 23:20:04
3.7K0
发布2019-10-14 23:20:04
举报
文章被收录于专栏:月小水长月小水长

实现的功能

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

该爬虫的功能主要分为三部分,第一个主打功能是爬取指定用户的所有微博(可以通过热键 Ctrl + P 快速打开),这个用户可以按照昵称搜索,可以选择是否只抓取原创微博,如下图

爬取的微博内容保存在 csv 文件中,表头包括微博id、微博正文、图片 url、发布位置、发布时间、发布工具和点赞数、评论数、转发数,其中图片 url 里面是所有微博图片的 url 以英文逗号间隔拼接起来的。

第二个主打功能是爬取指定话题下的所有微博(可通过热键 Ctrl+B快速打开),如下图

爬取话题微博保存的 csv 格式大致和爬取用户微博格式类似。

第三个主打功能就是爬取根据微博 id 爬取该微博下的所有评论详情,比如微博 id 为 IaYZIu0Ko 的所有评论为:

除了爬虫的业务逻辑,大家也可以在上面看到,有较为友好的操作界面,方便大家操作。

技术路线

代码共计 1000 余行,不关心技术的同学可以跳过此部分

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

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

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

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

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

核心代码讲解

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

代码语言:javascript
复制
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])

然后根据评论总数分页

代码语言:javascript
复制
pageNum = ceil(commentNum/10)

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

代码语言:javascript
复制
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 解析的,里面我遇到了许许多多的实用技巧,会在后续博客做详细展开。

本文参与?腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-10-11,如有侵权请联系?cloudcommunity@tencent.com 删除

本文分享自 月小水长 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 实现的功能
  • 技术路线
  • 核心代码讲解
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com