上接:第一章:爬虫基础简介
下接:第三章:数据解析(正则法)
老版本多使用urllib模块,已被request模块取代
2.2.2环境安装
①cmd:
pip install request
#爬取搜狗的首页数据
import requests
if __name__=="__main__":
#step1:指定url
url = 'http://www.sogou.com/'
#step2:发送请求
#同时get()方法会返回一个响应对象
response=requests.get(url=url)
#step3:获取相应数据
page_text = response.text
print(page_text)
#step4:持久化存储
with open("./sogou.html",'w',encoding='utf-8')as fp:
fp.write(page_text)
print("爬取数据结束!")
pass
输出结果:
可以代码正常运行,同时在当前项目下生成了相应的html格式的文件记录page_text保存的内容。
前提了解:
① query=
后对应我们要搜索的关键词
运用python中字典的相关知识可以将query变成一个实时输入关键字的状态。
② 准备UA伪装:一种反反爬策略
UA-User-Agent(请求载体的身份标识)
查看自己的UA可以:在当前页面点击鼠标右键——检查——如图红框
当然你也可以不用自己的身份标识
UA随机生成器
UA检测:就是在门户网站的服务器检测对应请求的载体身份标识时,如果检测到请求的载体身份为某一款浏览器的标识,则说明该请求是一个正常的请求,否则识别为一个不正常的请求(爬虫),那么服务器就会拒绝请求从而使爬虫无法爬取数据。
所以UA伪装:就是让爬虫对应的请求载体身份标识为伪装为某一款浏览器,然后get()函数中的headers参数就是user-agent()身份标识。
代码:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import requests
if __name__=="__main__":
#UA伪装
headers={
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.11 Safari/537.36'
}
url="https://www.sogou.com/web?query="
#处理url携带的参数:封装到字典中
kw=input('please enter a key word:')
param={
'query':kw
}
#对指定的url发起的请求,且请求过程可以处理参数,这就变成了一个实时动态的过程
response=requests.get(url,params=param,headers=headers)
page_text=response.text
filename =kw+'.html'
with open(filename,'w',encoding='utf-8')as fp:
fp.write(page_text)
pass
print(filename,'保存成功!')
pass
首先进入百度翻译,分析翻译部分存在Ajax请求
(AJAX 是一种用于创建快速动态网页的技术。
通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。)
通过F12抓包工具分析Ajax请求
确定URL和使用POST方法
鼠标右键当前的百度翻译页面——检查——如图红框
找到几个数据包中找到既为post请求,同时传参是我们输入的要翻译的字符的,这是因为我们需要爬取的数据并不是整个翻译页面的信息,我们只需要翻译“dog”得到的信息,这一步相当于就是寻找dog翻译在该页面对应的板块。
(在这里留个坑,我自己查看相应的请求时始终找不到翻译界面所对应的sug,意思就是我下面的图中显示的四个包不对,正确的应该是三个sug加两个另外的包,而代码中强制访问https://fanyi.baidu.com/sug是允许的。还没有想通~~)
同时注意回应的一组数据是json格式。
json.dump在默认情况下,对于非ascii字符生成的是相对应的字符编码,而非原始字符,所以调用json.dump时对应的参数ensure_ascii要改为false
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import requests
import json
if __name__ == "__main__":
# 1.UA伪装
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.11 Safari/537.36'
}
# 2.指定url
post_url = "https://fanyi.baidu.com/sug"
# 3.post请求参数处理(需要翻译的信息)
word = input('please enter a word you want to translate:')
data = {
'kw': word
}
# 4.请求发送
response = requests.post(url=post_url, data=data, headers=headers)
# 5.获取响应的数据:json()方法返回的是一个字典对象obj
# 注意上述方法只适用于相应数据是json串
dic_obj = response.json()
# 6.持久化存储
filename = word + '.json'
fp = open(filename, 'w', encoding='utf-8')
json.dump(obj=dic_obj, fp=fp, skipkeys=False,ensure_ascii=False)
print(filename, '翻译成功!')
pass
注意requests.get()中的params参数与抓包中显示的参数一致:
代码:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import requests
import json
if __name__=="__main__":
url="https://movie.douban.com/j/chart/top_list"
params={
'type':'24',
'interval_id': '100:90',
'action':'',
'start':'0' ,#从库中的第几部电影去取
'limit':'20',#一次取出的电影个数
}
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.11 Safari/537.36'
}
response = requests.get(url,params=params,headers=headers)
list_data = response.json()
fp=open('./douban.json','w',encoding='utf-8')
json.dump(list_data,fp=fp,ensure_ascii=False)
print("读取电影排名成功!")
pass
道理相同,不过这次抓包信息中的访问函数是post,代码也可以进行改进,将keyword动态化。
代码:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import json
import requests
if __name__ == "__main__":
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.11 Safari/537.36'
}
url = "http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword"
params ={
'cname':'',
'pid':'',
'keyword':"北京",
'pageIndex':'1',
'pageSize':'10',
}
response = requests.post(url=url,params=params,headers=headers)
get_data=response.json()
fp=open(".kfc_store_list.json",'w',encoding='utf-8')
json.dump(get_data,fp=fp,ensure_ascii=False)
print("获取地址信息成功!")
pass
http://scxk.nmpa.gov.cn:81/xk/
分为下列几个步骤:
①动态加载数据
②首页中对应的企业信息数据是通过ajax动态请求到的
但是此时网页显示的只是概览,并不是详情数据,需要我们选择某一栏打开才能看到诸多详情数据:
这意味着我们最后抓取的数据并不能通过药监局的url:http://scxk.nmpa.gov.cn:81/xk/
直接访问得到,即我们想要得到的数据属于:动态加载数据。
于是我们尝试这种动态加载数据是否可以通过ajex抓包进行获取
在鼠标进行点击时,我们成功捕获了一个请求,但我们不确定这是不是我们要寻找的,于是可以点击“回击”查看内容
内容是json格式看不懂,没有关系,格式化转化为汉字格式就可以确定内容是不是我们想要的
我们的想法得到了验证,首页中对应的企业信息数据是通过ajax动态请求得到的,同时我们仔细观察得到的数据和我们最终想要爬取的信息页面的url的练习可以发现:
③再对比其他超链接选项打开的页面,发现:
④详情页的企业详情数据也是动态加载出来的
观察后发现:
如下图:我们打开详情页之后发现加载的详细信息也有一个Ajax请求,说明也是动态数据:
切换回XHR信息,我们找到一个数据包,并且发现它的参数就是我们之前得到的ID
编写代码:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import requests
import json
if __name__=="__main__":
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.11 Safari/537.36'
}
#批量获取不同企业的id值
url="http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsList"
#参数的封装
data = {
'on':' true',
'page':' 1',#控制当前缩略页的页码
'pageSize':' 15',
'productName':'',
'conditionType':' 1',
'applyname':'',
'applysn':'',
}
json_ids=requests.post(url=url,headers=headers,data=data).json()
id_list = []#存储企业的id
detail_data_list=[]#存储所有的企业详情数据
for dic in json_ids['list']:
id_list.append(dic['ID'])
pass
#获取企业详情数据
post_url="http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsById"
for id in id_list:
data={
'id':id
}
detail_json=requests.post(url=url,headers=headers,data=data).json()
detail_data_list.append(detail_json)
pass
#持久化存储所有详情页信息
fp=open("detail.json",'w',encoding='utf-8')
json.dump(detail_data_list,fp=fp,ensure_ascii=False)
print("爬取成功!")
pass
python快速给headers等字典加上引号
首先选择我们要加引号的部分,然后ctrl+R
出现以下对话框,先选择右上角regex
然后在上方输入框输入(.*?):(.*)
下方输入'$1':'$2'
,
再点击replace all 就可以啦
结果: