实现简单小爬虫,爬取斗鱼直播页面所有当前在线直播列表信息
1 目标分析
爬取斗鱼直播页面所有当前在线直播列表信息,包括房间标题、主播名、所属类别、热度等信息。
2 分析URL
2.1 分析首页URL
打开斗鱼直播https://www.douyu.com/directory/all
很容易发现,通过https://www.douyu.com/directory/all链接打开网页时,浏览器加载的第一个文件(all)包含了页面上的所需的数据,JSS和CSS仅修改页面显示及动画,未修改数据。该请求获取的文件可能是缓存服务器中的数据。
2.2 分析换页URL
通过点击页2,发现浏览器地址栏URL没有发生改变,由此可知,换页操作是AJAX请求。
在加载的文件中,可以找到一个文件名为“2”的文件,包含JSON数据,其内容与页面直播信息一致,且其中’pgcnt’对应的值与最大页面数相同。
查看文件“2”的请求头信息,得到AJAX请求的URLhttps://www.douyu.com/gapi/rkc/directory/0_0/2
点击页3,也很容易就找到文件名为“3”的文件,其请求URL为https://www.douyu.com/gapi/rkc/directory/0_0/3,与“2”的请求URL差别仅在最后“/数字”的区别。
点击末页,会得到类似的结果。
再回头点击页1,发现也是AJAX请求,得到文件名为“1”的json文件,其请求URL为https://www.douyu.com/gapi/rkc/directory/0_0/1
2.3 确定爬取URL
由以上分析可以推断出,换页操作是AJAX请求,请求URL为:https://www.douyu.com/gapi/rkc/directory/0_0/num,num为对应页面数。
URL未加密,变化规律简单。
3 代码
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
import requests
class DouyuSpider:
def __init__(self):
""" 初始化DouyuSpider
创建一个斗鱼直播页面爬虫
"""
self.headers = {
'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36',
}
# 直播大厅:https://www.douyu.com/directory/all
# https://www.douyu.com/gapi/rkc/directory/0_0/2
self.start_url = 'https://www.douyu.com/gapi/rkc/directory/0_0/{:d}'
def fetch_one_page(self, offset):
""" 发起请求,获取响应数据
:param offset: 页面序号
:return response.content: 二进制响应体数据
"""
response = requests.get(
self.start_url.format(offset),
headers=self.headers
)
return response.content
def parse_json(self, content):
"""解析数据
:param content: 响应体二进制数据
:return items, pgcnt: 直播信息列表,当前最大页面数
"""
results = json.loads(content.decode())['data']
items = []
num = 0
for result in results['rl']:
item = {}
item['topic'] = result['c2name']
item['title'] = result['rn']
ol = result['ol'] / 10000
if ol == 0:
item['hot'] = '0'
else:
item['hot'] = f'{ol:.1f}万'
item['user'] = result['nn']
item['room_url'] = 'https://www.douyu.com/{}'.format(result['url'])
items.append(item)
num += 1
if num % 20 == 0:
print(f'完成第{num}条数据')
print(item)
return items, int(results['pgcnt'])
def save_content(self, items):
""" 保存数据
:param items: 直播信息列表
:return None:
"""
with open('douyu.json', 'a+', encoding='utf-8') as f:
for data in items:
json.dump(data, f, ensure_ascii=False)
f.write('\n')
def is_next(self, max_pages, offset):
""" 判断是否有下一页
:param max_pages: 当前最大页面数
:param offset: 已爬取页数
:return next_flag: 是否有下一页
"""
if offset < max_pages:
next_flag = True
if offset >= max_pages:
next_flag = False
return next_flag
def run(self):
""" 运行爬虫
开始爬取数据
"""
offset = 0
next_flag = True
while next_flag:
offset += 1
html = self.fetch_one_page(offset)
items, max_pages = self.parse_json(html)
self.save_content(items)
print('*'*10 + f'完成第{offset}页' + '*'*10)
print(f'最大页数{max_pages}')
next_flag = self.is_next(max_pages, offset)
# next_flag = False
print('已爬取所有页面')
if __name__ == '__main__':
dou_spider = DouyuSpider()
dou_spider.run()
4 总结
AJAX请求URL没有加密,所以非常容易获取服务器返回的JSON数据,解析JSON数据就能得到所需要的数据。