号外!号外!号外!
喜欢逛贴吧的朋友们,你们的福利来啦!经过本人的一顿操作,我写出了百度贴吧的通用爬虫,只需要输入你想爬取的贴吧名字就可以进行内容的爬取。
- 喜欢校花吗?来咱们一起看一看校花吧的首页吧
看看这忧郁的眼神,瞬间征服了多少宅男的心(手动滑稽)
百度贴吧的请求地址如下:
http://tieba.baidu.com/f?ie=utf-8&kw=校花&fr=search&red_tag=r2338324287
得到要请求的url之后进行胡乱分析(肯定是认真的啦),正如我们所见到的,这个url还是有那么一点点长的。其实啊,里面有一些东西是在我们爬虫里面用不到的,你比如咱们把fr字段和red_tag字段删掉,再请求一哈,肯定也是成功的啦,这时候的请求地址会相对简洁,当然啦,ie字段和对应的内容也是可以删除的。只有kw对应的字段是我们需要的,而kw对应的字段正是我们贴吧的名字。删减后的url地址如下:
http://tieba.baidu.com/f?kw=校花
到了这里你是不是觉得已经完事儿了呢?当然不是!像这么大的吧肯定不止只有一页内容,所以我们来到当前页的底部,清楚的看到有很多页,如下
那点击下一页看看咯,注意注意注意(敲黑板啦),注意看一下当前的url有没有变化。点击下一页之后的url地址:
http://tieba.baidu.com/f?kw=校花&ie=utf-8&pn=50
多了个ie和pn字段,前面我们已经说过ie字段是可以删掉的,因此pn字段肯定是控制页码的字段。为了验证以及寻找规律,咱们继续点击下一页。并观察url的变化。
http://tieba.baidu.com/f?kw=校花&ie=utf-8&pn=100
这时pn字段对应的值变成了100,经过反复点击之后,我发现每次pn的变化都是累加50
且首页的pn值为0,即我们请求的其实url应该是它:
http://tieba.baidu.com/f?kw=校花&pn=0
好了,接下来就要分析页面了,咱们一步一步走通之后再写代码,进行调试。
首页,在检查模式下的network中找到我们响应的url,并保存headers里面的部分内容,这是为了咱们模拟请求的时候用的。具体如下图:
在response中寻找我们要找提取的数据,可以直接Ctrl+f在response里面搜索你看到帖子的标题
这就是帖子的标题,title对应的字段就是帖子的url地址,这下都找到了,很棒啦。,但是它是绿色的,为什么是绿色的啊?好好的为什么是绿色的啊?我们继续往上翻。果然不出我所料,注释了。莫非这就是百度贴吧的反爬手段?
查看网页源码之后发现我们所需要的内容是在code标签里面,接下来就是对它的请求与解析啦,直接上代码啦:
import requests
import json
import re
class TiebaSpider:
def __init__(self, tieba_name):
self.tieba_name = tieba_name
self.start_url = "http://tieba.baidu.com/f?kw=" + tieba_name + "&pn=0"
self.part_url = "http://tieba.baidu.com"
self.headers = {
"accept-encoding": "gzip, deflate",
"accept-language": "zh-CN,zh;q=0.9",
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.75 Safari/537.36"
}
def save_content_list(self, content_list):
file_path = self.tieba_name + ".txt"
with open(file_path, "a", encoding="utf-8") as f:
# 遍历列表 分别写入
for content in content_list:
f.write(json.dumps(content, ensure_ascii=False, indent=2))
f.write("\n")
def parse_url(self, url):
print(url)
toggle = False
curr_pagen = int(re.findall(r'&pn=(\d+)', url)[0])
# 构造下一页url
next_pagen = re.sub(r'&pn=(\d+)', r'&pn={}'.format(curr_pagen + 50), url)
# 发送请求,获取响应
response = requests.get(url, headers=self.headers, timeout=20)
html_str = response.content.decode()
# 使用正则提取全部img_url
img_url_list = re.findall('bpic *= *"([^"]+)', html_str)
# 提取"/p/6086393083" title="感觉自己萌萌哒" target="_blank" class="j_th_tit ">感觉自己萌萌哒
title_list = re.findall('<a rel=\"noreferrer\" href=(.*?)</a>', html_str)
content_list = []
for title in title_list:
toggle = True
item = {}
# 提取title内容
title_temp = re.search(">(.*?)<", title + "<")
item["title"] = list(title_temp.groups())[0]
# 提取href内容
href_temp = re.search("\"(.*?)\"", title)
item["href"] = self.part_url + list(href_temp.groups())[0] # 我们得到的img_url是这样的/p/6052917512,所以此处要拼接
print(item["href"])
# 提取img_url内容
item["img_list"] = [img_url for img_url in img_url_list][0]
# 把得到的数据添加到一个列表里面
content_list.append(item)
self.save_content_list(content_list)
return toggle, next_pagen
def run(self):
toggle, next_url = self.parse_url(self.start_url)
while toggle:
toggle, next_url = self.parse_url(next_url)
if __name__ == '__main__':
tieba_spider = TiebaSpider("校花")
tieba_spider.run()
运行之后咱们看一下结果
很快就爬取了100条数据,这里我手动暂停了,有兴趣的同志们可以让它一直运行下去,咱们再来看看爬取保存的结果
我们要的数据都在这里保存啦,可以说基本成功啦。
做自己的舔狗,嘻嘻嘻。这段代码我总觉得不够完美,所有请路过的大佬斧正,共同进步!
另外非常感谢一位不愿透露姓名的大佬指点,非常感谢!