最近做了一个完整版的百度贴啊全吧爬虫,过程比较具有代表性,分析过来供大家参考。代码在解禁后后贴吧爬虫查看。
-
项目结构
项目主要采用scrap-redis框架,为分布式爬虫。数据采集完成后存储于mongodb数据库中。 -
项目思路
主要思路很简单,就是帖子->帖子下的回复->帖子回复下的评论逐级抓取。 -
项目特性
- 抓取完整的帖子,包括所有的评论。
- 对帖子结构进行完整解析,包括评论下的对话信息。
- 实时抓取最新帖子。
- 自动将所有帖子和评论组合成一个对象。
-
实现方法
经过对贴吧的分析,可以发现贴吧内容相关的三个url为:
帖子本身url:
"https://tieba.baidu.com/f?ie=utf-8&kw={0}&pn={1}"
# 参数{0}为关键字 如 李毅
# 参数{1}为页数 是50的倍数
回复的url:
'https://tieba.baidu.com/p/{0}'
'https://tieba.baidu.com/p/{0}?pn={1}'
# 参数{0}是帖子的id
# 参数{1}是页数 1,2,3,4...
楼层回复下帖子的url
"https://tieba.baidu.com/p/comment?tid={0}&pid={1}&pn={2}"
# 参数{0}是帖子的id thread_id
# 参数{1}是回复的id post_id
# 参数{2}是有评论的页数 1,2,3...
有了最基本的这几个url就可以开始愉快地进行抓取了~
但是scrapy抓取需要层层递进的内容有一个问题,就是每个统一的结构里面的内容都是分开的,这样对于一些需要实时线上的应用的查询会造成很大的问题,因此需要一个“组装器”对所有的数据进行组装。为此,我的项目结构改写如下图:
爬虫数据流.jpg
多个爬虫先将数据放入redis中,然后一个守护进程循环判断是否有新的已经爬完的帖子并且从redis中get到并且组装起来,放到Momgodb当中。这也就是在item当中为什么会看到那么多标志位的原因。
附录:
-
数据结构设计
-
tieba_post item
字段 | 含义 | 功能 | 类型 |
---|---|---|---|
title | 帖子的标题 | \ | string |
url | 帖子的url | \ | string |
reply_nums | 帖子的回复数量 | \ | int |
post_time | 发帖时间 | \ | time |
last_reply_time | 最后一次回复的时间 | \ | time |
post_id | 帖子的id | \ | long num |
author | 帖子的作者 | \ | string |
source | 源 | 用于标记源 | string |
reply_page_num | 帖子下的回复一共有多少页 | 用于记录总共回复的页数 | int |
- tieba_reply_item
字段 | 含义 | 功能 | 类型 |
---|---|---|---|
author | 作者 | \ | string |
content | 内容 | \ | string |
reply_time | 回复的时间 | \ | int |
reply_id | 回复的Id | \ | long num |
floor | 楼层 | \ | int |
post_id | 帖子的id | \ | long num |
source | 源 | 用于标记源 | string |
comment_page_num | 评论页数 | reply底下的评论一共有多少页 | string |
cur_reply_page_num | 现在位于的reply页数 | 用于记录现在的reply页数 | int |
- tieba_comment_item
字段 | 含义 | 功能 | 类型 |
---|---|---|---|
author | 作者 | \ | string |
content | 内容 | \ | string |
comment_time | 评论的时间 | \ | int |
reply_id | 回复的Id | \ | long num |
stair | 楼层 | \ | int |
page | 页数 | \ | int |
is_reply | 是否回复别人 | 1为回复别人0反之 | int |
reply_to | 回复给谁 | / | string |
post_id | 帖子的id | \ | long num |
source | 源 | 用于标记源 | string |
is_empty | 评论是否为空 | 1 true 0 false | int |
cur_comment_page_num | 现在位于的comment页数 | 用于记录现在的reply页数 | int |
total_comment_page_num | 一共有多少评论页数 | / | int |
网友评论