1 requests模块
python中原生的一款基于网络请求的模块,功能强大,简单便捷,效率极高
作用:模拟浏览器发送请求
使用:(requests模块的使用流程)
- 指定url 网址
- 发起请求
- 获取响应数据
- 持久化存储响应数据
首先要pip install requests
2 实战:爬取搜狗首页的页面数据
import requests
if __name__ == "__main__":
# step1: 指定url
url = "https://www.sogou.com/"
# step2: 发起请求
# get方法会返回一个响应对象
responds = requests.get(url = url)
# step3:响应数据的获取,字符串形式
page_text = responds.text
print(page_text)
# step4: 持久化数据
with open("D:/pachong/sogou.txt","w",encoding = "utf-8") as f:
f.write(page_text)
print("爬取数据结束")
3 实战:破解百度翻译
不再爬取整个页面了,只爬取翻译到的文本
UA检测&UA伪装:反爬与反反爬机制
观察网址变成了带dog的,读取这张页面的信息能找到翻译结果。
这里翻译的时候出现了局部刷新的情况,存在局部刷新的包,捕捉这些包里面发送刷新局部页面的包:
在XHR中逐个查看包中的post和请求信息(request)
对应的是一个post请求,且携带了参数,相应的数据是一个json数据
import requests
import json
if __name__ == "__main__":
# 1.url指定
post_url = "https://fanyi.baidu.com/sug"
# 2.进行UA伪装
headers = {"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36 Edg/88.0.705.74"}
# 3.发送一个post请求,post可以携带数据
data = {"kw":'dog'} # 没有参数也可以不加data
response = requests.post(url = post_url, data = data, headers = headers) # 返回一个相应
print(response.text) #得到相应的字符串形式
print(response.json()) #得到json字典
dic_obj = response.json()
#进行持久化存储,存储为json文件
fp = open(r"D:\pachong\Day2\dog.json","w", encoding = "utf-8")
json.dump(obj = dic_obj, fp = fp, ensure_ascii = False) # 中文不能使用ASCII编码的
print("over!!!")
其中,post的参数可以从sug包里面看到应该是一个字典,形式如下:
进行UA伪装的时候,可以根据User-Agent伪装
在确认是json形式的数据之后,可以直接.json()获取一个字典对象,可以从Content-Type看出来
这样可以实现对任意单词的翻译:
import requests
import json
if __name__ == "__main__":
# 1.url指定
post_url = "https://fanyi.baidu.com/sug"
# 2.进行UA伪装
headers = {"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36 Edg/88.0.705.74"}
# 3.发送一个post请求,post可以携带数据
word = input("输入一个单词:")
data = {"kw":word} # 没有参数也可以不加data
response = requests.post(url = post_url, data = data, headers = headers) # 返回一个相应
# print(response.text) #得到相应的字符串形式
# print(response.json()) #得到json字典
dic_obj = response.json()
print(dic_obj["data"][0]["v"])
只能对单个单词翻译!
4 实战:爬取豆瓣电影分类排行榜https://movie.douban.com/中的电影详情
点开豆瓣电影排行榜里的戏剧排行榜,打开局部请求的数据抓包情况,XHR包
随着网页上鼠标的下滑,页面会发送一个局部页面刷新的请求,就是新刷新出来的电影信息
那随着下滑,页面刷新会发现,多了一些局部信息请求的包,那这些
查看请求得到的响应的数据类型,还是json类型
打开响应,也可以看到响应的具体内容
import requests
import json
import pandas as pd
if __name__ == "__main__":
# 1.url指定
post_url = "https://movie.douban.com/j/chart/top_list"
# 这里网址里面有参数,将参数单独拿出来
param = {
"type": "24",
"interval_id" : "100:90",
"action": " ",
"start": "0", # 从排名60开始
"limit": "20" # 一次请求取出20个
}
# 2 UA伪装
headers = {"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36 Edg/88.0.705.74"}
# 3 get请求
response = requests.get(url = post_url, params = param, headers = headers)
response = response.json()
print(response)
# 持久化数据
fp = open("movie_rank.json","w",encoding = "utf-8")
json.dump(response, fp, ensure_ascii = False)
如果要将爬取的数据变成表格按列存储起来,可以将json数据形式变成dataframe:
# 持久化数据
fp = open("movie_rank.json","w",encoding = "utf-8")
json.dump(response, fp, ensure_ascii = False)
dic = response[0]
k = dic.keys()
df = pd.DataFrame(response)
oder = k
file_path = pd.ExcelWriter('movie_rank.xlsx') # 打开excel文件
df = df[oder] # 按指定顺序排序df的各个属性
# 替换空单元格
df.fillna(' ', inplace=True)
# 输出
df.to_excel(file_path, encoding='utf-8', index=False,sheet_name="sheet1")
file_path.save()
5 实战:爬取肯德基查询网站中指定地点的餐厅数量
在肯德基餐厅信息查询网址 http://www.kfc.com.cn/kfccda/storelist/index.aspx 里面
在搜索框中搜索“北京”,发现网址并没有变化,说明发送的请求是一个局部刷新请求,Ajax请求
对于Ajax请求都可以在XHR里面找到发送的请求包,根据这个包的样式,可以伪装成浏览器进行数据的爬取
那这里点了四页信息,抓取出来了四个包
可以查看param情况,和获取的response的数据类型
此处拿到的不再是json串了,拿到了一个的是一个text,注意
import requests
import json
import pandas as pd
if __name__ == "__main__":
# 指定url
post_url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword'
# post_url = "http://www.kfc.com.cn/kfccda/storelist/index.aspx"
params = {
"cname":"",
"pid":"",
"keyword": "北京",
"pageIndex": "7",
"pageSize": "10"
}
# UA伪装
headers = {"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36 Edg/88.0.705.74"}
# 3 get请求
response = requests.get(url = post_url, params = params, headers = headers)
response = response.text
print(response)
# 持久化数据
with open("D:/pachong/Day2/kfc_place.txt","w",encoding = "utf-8") as f:
f.write(response)
这里的网址也是带参数的,要是不带参数,就要把参数传到params里面
如果要爬取每一页的信息下来,那么只需要加一个循环:
import requests
import json
import pandas as pd
t = ""
if __name__ == "__main__":
# 指定url
post_url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx'
for ind in range(1,8):
params = {
"op":"keyword",
"cname":"",
"pid":"",
"keyword": "北京",
"pageIndex": str(ind),
"pageSize": "10"
}
# UA伪装
headers = {"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36 Edg/88.0.705.74"}
# 3 get请求
response = requests.get(url = post_url, params = params, headers = headers)
response = response.text
t = t + '\n' + response
print(t)
t里面储存的就是每一页的信息,加一些匹配查找,就可以找出地址,后面还可以存储到excel表格里面
6 实战:爬取国家药品监督管理局中基于化妆品生产许可证的相关数据
根据网址提供的这些许可证书,爬取每个证书的详细信息,就是点进去之后的信息,网址发生变化,不是局部刷新,是根据超链接跳转了页面。
http://scxk.nmpa.gov.cn:81/xk/
首先看一下,对网址发请求,能不能得到每个许可证的超链接。
import requests
import json
import pandas as pd
if __name__ == "__main__":
url = "http://scxk.nmpa.gov.cn:81/xk/"
headers = {"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36 Edg/88.0.705.74"}
response = requests.get(url, headers = headers)
response = response.text
with open("jiaojianju.html","w") as f:
f.write(response)
将保存的html文件用网页打开看,发现是这样的
没有得到许可证目录,为什么会这样呢?
说明这组数据不是通过"http://scxk.nmpa.gov.cn:81/xk/"网址请求到的,是通过动态请求到的,这里查看AJAX请求的包,发现有这么一个包,响应里面有我们要的数据
通过对详细信息的网址观察,可以看出id值加到网址后面,就是每个证书详情页的url
import requests
import json
import pandas as pd
if __name__ == "__main__":
url = "http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsList"
params = {
'on': 'true',
'page': '1',
'pageSize': '15',
'productName': '',
'conditionType': '1',
'applyname': '',
'applysn':'',
}
headers = {"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36 Edg/88.0.705.74"}
response = requests.post(url = url, data = params, headers = headers)
response = response.json()
print(response)
注意,写post的时候参数是data,而写get的时候,参数是params,这里用get请求不到数据,但是用post可以,不知道为啥(以后决定多用post)
详情页中的详情信息也是动态请求到的,AJAX请求
参数的id可以通过首页的信息得到,所有请求的url都是一样的,只有id不一样,所以通过对参数的调整完成详情页的AJAX请求
这里首先要把id从response中提取出来
import requests
import json
import pandas as pd
if __name__ == "__main__":
url = "http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsList"
id_lis = []
for y in range(10): # 爬一百页信息
params = {
'on': 'true',
'page': str(y + 1),
'pageSize': '15',
'productName': '',
'conditionType': '1',
'applyname': '',
'applysn':'',
}
headers = {"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36 Edg/88.0.705.74"}
response = requests.post(url = url, data = params, headers = headers)
response = response.json()
# print(response)
lis = response['list']
for i in lis:
id_lis.append(i['ID'])
print(len(id_lis))
这里把10页的150条公司id列举出来了(本来循环了100页,但是到第50页的时候出错了,发现根本没有第50页,是真狗啊!!),根据id来查询详情页信息,并且把详细信息都存储在excel里面
# 在url里面分别查询id参数时候的结果
m_lis = []
url_ = "http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsById"
for id in id_lis:
data = {"id": id}
message = requests.post(url = url_ , data = data, headers = headers).json()
m_lis.append(message)
df = pd.DataFrame(m_lis) #DataFrame的参数必须是一个[{},{},{},{},...]类型的
file_path = pd.ExcelWriter('yaojianju.xlsx') # 打开excel文件
# 替换空单元格
df.fillna(' ', inplace=True)
# 输出
df.to_excel(file_path, encoding='utf-8', index=False,sheet_name="sheet1")
file_path.save()