当访问的页面是一个动态页面,就需要我们使用Ajax请求。
AJAX 是 Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)的缩写。AJAX 通过使用原有的 web 标准组件,实现了在不重新加载整个页面的情况下,与服务器进行数据交互。例如在新浪微博中,你可以展开一条微博的评论,而不需要重新加载,或者打开一个新的页面。但是这些内容并不是一开始就在页面中的(这样页面就太大了),而是在你点击的时候被加载进来的。这就导致了你抓取这个页面的时候,并不能获得这些评论信息(因为你没有『展开』)。
AJAX 的一种常见用法是使用 AJAX 加载 JSON 数据,然后在浏览器端渲染。如果能直接抓取到 JSON 数据,会比 HTML 更容易解析。
AJAX 实际上也是通过 HTTP 传输数据的。
AJAX 一般是通过 XMLHttpRequest 对象接口发送请求的,XMLHttpRequest 一般被缩写为 XHR。点击网络面板上漏斗形的过滤按钮,过滤出 XHR 请求。挨个查看每个请求,通过访问路径和预览,找到包含信息的请求。
如果页面是一个动态的json数据,就需要Ajax请求。
案例一:
需求:
实现输入一个单词,出现翻译结果,并储存到 json 文件中。
代码实现:
import requests
import json
if __name__ == '__main__':
# 1.指定url
url = 'https://fanyi.baidu.com/sug'
# 2.进行UA伪装
header = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3775.400 QQBrowser/10.6.4208.400'
}
# 3.参数处理
# data相当于get请求中的params,表示请求所带的参数(也是一个字典类型数据)
# post请求参数处理(和get请求一致)
word = input('请输入要翻译的单词:') # 这样翻译单词就变成动态的了
data = {
'kw':word
}
# 4.请求发送
response = requests.post(url=url,data=data,headers=header)
# 5.获取相应数据
# json()方法返回的是一个对象
# 如果确定相应数据是json类型的,才可以使用json()方法进行对象的返回
dic_obj = response.json()
print(dic_obj)
print('数据打印结束!')
# 5.进行持续化存储
file_name = word + '.json'
fp = open(file_name,'w',endcoding='utf-8')
json.dump(dic_obj,fp=fp,ensure_ascii=False)
print('数据存储结束!')
案例二:
需求:
实现读取豆瓣电影信息。
代码实现:
import requests
import json
if __name__ == '__main__':
url = 'https://movie.douban.com/j/chart/top_list'
param = {
'type': '24',
'interval_id': '100:90',
'action': '',
'start': '0', # 从库中的第几个元素取
'limit': '20', # 一次取几个
}
header = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36'
}
response = requests.get(url=url,params=param,headers=header)
list_data = response.json()
# 打印结果
for i in list_data:
print(i)
# 也可以这样直接打印:
# print(list_data)
案例三:
需求:
爬取肯德基餐厅查询,指定地点的餐厅数量。
网址:http://www.kfc.com.cn/kfccda/storelist/index.aspx
代码实现:
# 爬取想要爬取城市的肯德基餐厅信息
import requests
import json
if __name__ == '__main__':
# 指定url
url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword'
# 动态输入查找的城市
city = input('请输入您想要查找的城市:')
# 参数处理
param = {
'cname': '',
'pid': '',
'keyword': city, # 城市名称
'pageIndex': '1', # 页面
'pageSize': '10', # 一页显示多少数据
}
# 进行UA伪装
header = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36'
}
# 获取相应数据
response = requests.post(url=url,data=param,headers=header)
# 这个页面是一个text,不是json
page_text = response.text
print(page_text)
print('数据爬取成功!')
案例四:
需求:
爬取国家药品监督管理局中化妆品生产许可信息管理系统服务平台,其中每个企业的详细信息。
网址:http://scxk.nmpa.gov.cn:81/xk/
思路:
我们可以发现这是一个json动态页面,需要我们使用Ajax请求抓取页面数据。但是我们需要打印每个公司的详细信息,我们点开不同公司的详细信息后发现,每个公司的网址前面的都是相同的(都是:http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsById),唯一不同的是后面的id信息。而这个id可以从首页中抓取。
所有,我们只需要通过post方法抓取到首页信息,再将id信息存入名为id_list(自己定义的名字,任何名字都可以)的列表中即可。
我们得到id_list列表信息后,就可再次用post方法抓取这个页面的企业详细信息。通过遍历id信息,来查找每个企业的详细信息,并且打印。
最后,我们发现这个网址有300多页,如果我们想把所有页的所有企业的详细信息都打印下来怎么办呢?我们发现参数param中的page是一个动态变量,其代表的就是页码数。我们只需要通过for循环将页码数变量,即可完成对所有(也可以是任意页,可以从第n页到第m页,只需要控制for循环内的参数即可)页码所有企业详细信息数据的抓取打印。
代码实现:
import requests
import json
if __name__ == '__main__':
# 指定url,国家药品监督总局化妆品生产许可信息管理服务平台
url = 'http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsList'
# 进行UA伪装
header = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36'
}
id_list = [] # 存贮id信息(需要定义在循环外,要不然就相当于每次循环都创建一个名为id_list的列表,会报错)
# 从第一页到第六页信息(也可以是从第n页到第m页)
# page为动态变量表示的是页码数
for page in range(1,6):
page = str(page)
# 参数处理
param = {
'on': 'true',
'page' : page, # 页码数
'pageSize' : '15', # 一页只有15个企业
'productName': '',
'conditionType': '1', # 从第一个企业开始
'applyname': '',
'applysn': ''
}
# 获取相应数据
# 为了获取所有企业的id
response = requests.post(url=url,data=param,headers=header)
json_id = response.json()
# print(json_id)
# 将id信息存入列表中
for dic in json_id['list']:
id_list.append(dic['ID'])
# print(id_list)
# 获取企业详细信息
# 每个企业的化妆品生产许可信息
url1 = 'http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsById'
# 遍历列表中的id信息,用post方法抓取数据,打印企业详细信息
for i in id_list:
data = {
'id': i
}
page_post = requests.post(url=url1,headers=header,data=data).json()
print(page_post)