游戏贴吧数据爬取和分析

百度贴吧的游戏品类下面,包含所有游戏贴吧的入口链接。从这个页面入手,可以拿到所有游戏贴吧的人气数据,对游戏名称、游戏类型、关注者数量、帖子数量等进行数据分析。

游戏贴吧总集

GitHub 地址:https://github.com/YicongCao/TiebaGameMeta

大致思路

这张页面为起点,按如下次序分别补完游戏树

关键路径

爬取这些数据,需要考虑以下几点:

0. 广度优先 vs 深度优先

构建 游戏树 有两条路径:广度优先遍历和深度优先遍历,前者先获取完整的品类索引,然后获取每个品类下完整的所有贴吧链接,最后扁平化地便利每个贴吧。相比深度优先,广度优先能先拿到索引信息,而且在断点续传方面有天然优势,所以用膝盖想一下就能知道要采用广度优先的方式进行遍历。

1. 大量索引的本地缓存

光是游戏类型的索引链接,就分很多页,如“客户端网游”这个类型,包含 10314 个贴吧、分 52 页。

每次请求能获得 200 个游戏贴吧的链接,一共 59859 个游戏贴吧,光是索引的获取,就要进行 300 次 HTTP 交互。

爬虫可能会遇到失败,会需要进行重试,如果每次执行爬虫时,都要重新获取这些数据,是很麻烦的,而且这些数据属于 冷数据 ,更新频率很慢。

所以要把 游戏树 的 json 数据,dump 到本地,下次启动爬虫时如果已经存在索引数据,直接加载使用即可。

2. 更大量子任务的分发

graph LR
下载HTML-->|IO耗时|解析HTML
解析HTML-->|CPU耗时|数据落地
数据落地-->CSV归档
数据落地-->存入DB

接近六万个贴吧,对每个贴吧获取其 HTML 文本、解析 HTML、数据入库,这里有这些坑:

  • 百度不傻,有反爬虫机制,监测到爬虫行为时 HTTP 请求的时间会延长、差不多每个 HTTP 请求都要花费 >1.0 秒的时间才能返回
  • 解析 HTML 也是耗时较长的任务,上面是 I/O 耗时,解析则是 CPU 耗时
  • 入库时有冲突,这么大的数据量,必然不会串行爬取,而并行的话,如果对同一个 csv 文件、或者同一个 db 连接进行操作,肯定会遇到线程锁的问题

就既然已经预见到这些问题,不如趁早绕路走,而不是跳进 反爬虫的坑多线程的坑。解决方法如下:

  • 使用消息队列,不要自己编写多线程逻辑,将对六万个贴吧首页的爬取,扔到 celery 里去完成
  • 每个任务自己搞定信息存储问题,不要过早入库、或者都写到一个文件里
  • 编写离线爬虫,在消息队列搞定 HTML 的下载之后,在本地统一做解析、统计、入库逻辑
  • (这条偷懒没做)如果解析 HTML 也耗时过久,将解析 HTML 的工作也扔进消息队列里,在各自的子目录暂存统计信息,最后再编写统一的入库脚本

总体思想就是,把 I/O 耗时的 HTML 下载操作、和 CPU 耗时的解析操作 解耦,将有状态的任务拆解成无状态的任务,将在线爬虫改成离线爬虫,然后把耗时且重复的操作,扔给消息队列去处理

离线爬虫思想

食用方法

先拉起 redis 作为 celery 的后端,再启动 celery,最后启动爬虫。

1
2
3
4
5
6
7
8
9
# 接收6万个贴吧的子任务
redis-server &
/Users/pulsar/anaconda3/bin/celery -A asynctask worker --loglevel=info
# 爬取贴吧索引
python3 ./spider.py
# 消息队列结束后,执行离线爬虫
python3 ./spideroffline.py
# 消息存档和入库
python3 ./csv2sqlite.py

有趣的东西

来看一下马里奥系列,在贴吧的受众群体:

嗯,超马、马车、网球是最热门的。

大家关于王者荣耀,都关心哪些话题:

原来游戏物品交易、代练、账号买卖是大家最关心的话题。

那么总体上最火的贴吧是哪几个呢(人气数据很相近的贴吧,应该是同一个贴吧的重定向版本)?

逃(