您的位置:首页 > 运维架构 > 网站架构

爬取【ajax+json】异步加载的网站

2018-02-04 10:02 281 查看
@导入类库

import requests
from lxml import etree
import json
import time


@请求地址和请求头

# 请求头,用于伪装客户端浏览器,可由抓包获取
header_base = {
'Connection': 'keep-alive',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36',
'Upgrade-Insecure-Requests': '1',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'zh-CN,zh;q=0.9',
}

# 首页 URL
url_str = 'https://www.douyu.com/directory/all'


@发起请求,并获得html文档的页面元素树

# 获取首页信息
response = requests.get(url=url_str, headers=header_base)
# print(response.text)
# print(response.status_code)

# 获得页面的元素树
html = etree.HTML(response.text)


@解析首页信息

# 通过xpath提取房间信息:播主和在线人数
info_list = html.xpath(
"//ul[@id='live-list-contentbox']//span[@class='dy-name ellipsis fl']/text() \
| //ul[@id='live-list-contentbox']//span[@class='dy-num fr']/text()"
)

# 播主昵称
host_names = info_list[0]
print('first_name : ', host_names)

# 打印所有房间信息
for info in info_list:
print(info)


@点击首页底部的分页页码时,地址栏不会发生变化,由此我们知道该网站的分页信息是通过ajax做异步加载的



# 这里我们发现当点击第二页时,浏览器的地址栏并没有发生变化
# 无法直接从页面获取页码,因为页码是通过JS生成的
# page_num = html.xpath("//a[@class='shark-pager-item']/text()")
# print('page_num : ', page_num)


@知道了分页数据的加载地址之后,我们逐页发起请求,获取其json数据,并做分析和提取

# 该网站的分页数据是通过ajax异步加载的(无法直接从浏览器的地址栏获取其页面的URL)
# 需要借助抓包工具或页面控制台获得ajax异步请求所发送请求的url
page = 1
while True:

# 不断爬取下一页
page += 1

# 通过抓包分析获得的分页地址
url_str = 'https://www.douyu.com/gapi/rkc/directory/0_0/' + str(page)
print(url_str)

# 请求房间信息
response = requests.get(url=url_str, headers=header_base)
# print(response.text)

# 从第二页开始,数据以json格式加载,因此先将文本转换为json
info_json = json.loads(response.text)
# print(type(info_json['data']['rl']))

# 当请求的页码大于最大页码时返回的是第一页数据
# 我们以此作为循环退出条件
print('========', info_json['data']['rl'][0]['nn'],"==========")
if host_names == info_json['data']['rl'][0]['nn']:
break

# 分析json信息,循环获取每个直播房间的信息
for one_info in info_json['data']['rl']:

# 获取主播名称
host = one_info['nn']

# 获取直播在看人数
onlines = one_info['ol']

# 睡一会再接着爬下一页,以免请求过于频繁被反爬
time.sleep(2)


@爬取效果



@完整代码

import requests
from lxml import etree
import json
import time

# 请求头,用于伪装客户端浏览器,可由抓包获取 header_base = { 'Connection': 'keep-alive', 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36', 'Upgrade-Insecure-Requests': '1', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate, br', 'Accept-Language': 'zh-CN,zh;q=0.9', } # 首页 URL url_str = 'https://www.douyu.com/directory/all'

# 获取首页信息 response = requests.get(url=url_str, headers=header_base) # print(response.text) # print(response.status_code) # 获得页面的元素树 html = etree.HTML(response.text)

# 通过xpath提取房间信息:播主和在线人数 info_list = html.xpath( "//ul[@id='live-list-contentbox']//span[@class='dy-name ellipsis fl']/text() \ | //ul[@id='live-list-contentbox']//span[@class='dy-num fr']/text()" ) # 播主昵称 host_names = info_list[0] print('first_name : ', host_names) # 打印所有房间信息 for info in info_list: print(info)

# 这里我们发现当点击第二页时,浏览器的地址栏并没有发生变化 # 无法直接从页面获取页码,因为页码是通过JS生成的 # page_num = html.xpath("//a[@class='shark-pager-item']/text()") # print('page_num : ', page_num)

# 该网站的分页数据是通过ajax异步加载的(无法直接从浏览器的地址栏获取其页面的URL)
# 需要借助抓包工具或页面控制台获得ajax异步请求所发送请求的url
page = 1
while True:

# 不断爬取下一页
page += 30

# 通过抓包分析获得的分页地址
url_str = 'https://www.douyu.com/gapi/rkc/directory/0_0/' + str(page)
print(url_str)

# 请求房间信息
response = requests.get(url=url_str, headers=header_base)
# print(response.text)

# 从第二页开始,数据以json格式加载,因此先将文本转换为json
info_json = json.loads(response.text)
# print(type(info_json['data']['rl']))

# 当请求的页码大于最大页码时返回的是第一页数据
# 我们以此作为循环退出条件
print('========', info_json['data']['rl'][0]['nn'],"==========")
if host_names == info_json['data']['rl'][0]['nn']:
break

# 分析json信息,循环获取每个直播房间的信息
for one_info in info_json['data']['rl']:

# 获取主播名称
host = one_info['nn']

# 获取直播在看人数
onlines = one_info['ol']

# 睡一会再接着爬下一页,以免请求过于频繁被反爬
time.sleep(2)

print('OVER !!!')
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐