目录
3.2 爬取搜狗指定词条对应的搜索结果页面(简易网页采集器)
3.4 练习四:爬取豆瓣电影分类排行榜 https://movie.douban.com/ 中的电影详情数据
3.5 练习五:爬取肯德基餐厅查询http://www.kfc.com.cn/kfccda/storelist/index.aspx中指定的餐厅数据
一、简介
了解爬虫
- 什么是爬虫?
通过编写程序,模拟浏览器上网,然后让其去互联网上抓取数据的过程
- 爬虫合法性
-- 在法律上是不被禁止的
-- 具有违法风险
-- 善意爬虫 与 恶意爬虫
- 爬虫的应用场景
-- 通用爬虫那个
抓取系统的重要组成成分。抓取的是一整张页面数据
-- 聚焦爬虫
是建立在通用爬虫的基础之上。抓取的是页面中特定的局部内容
-- 增量式爬虫
检测网站中数据更新的情况。只会抓取网站中最新更新出来的数据
- 爬虫的矛与盾
-- 反爬机制
门户网站,可以通过相应的策略或者技术手段,防止爬虫程序进行网站数据爬取
-- 反反爬策略
爬虫程序可以通过制定相应的策略或技术手段,破解门户网站中那个具备的反爬机制,从而可以获取门户网站中相关的数据
-- robots.txt协议
君子协议。规定了网站中哪些数据可以被爬虫爬取,哪些数据不可以被爬取
二、网络协议
2.1 http协议
- 概念:就是服务器和客户端进行数据交互的一种形式
- 常用请求头信息:
User-Agent | 请求载体的身份标识 |
Connection | 请求完毕,是断开连接还是保持连接 |
- 常用响应头信息:
Content-Type | 服务器响应客户端的数据类型 |
UA伪装:让爬虫对应的请求载体身份标识伪装成某一款浏览器
UA检测:门户网站的服务器会检测对应请求的载体身份标识,如果检测到请求的载体身份标识为某一款浏览器,就说明该请求是一个正常的请求。但是,如果检测到请求的载体身份不是基于某一款浏览器的,则表示该请求为不正常请求(爬虫)
2.2 https协议
- 安全的超文本传输协议,是一个安全通信通道,它基于HTTP开发用于在客户计算机和服务器之间交换信息。它使用安全套接字层(SSL)进行信息交换,简单来说它是HTTP的安全版,是使用TLS/SSL加密的HTTP协议。
- 作用机制:
(1).对数据进行加密,并建立一个信息安全通道,来保证传输过程中的数据安全
(2).对网站服务器进行真实身份认证
- 加密方式
- 1.对称性密钥加密
在对称加密算法中,数据发信方将明文(原始数据)和加密密钥一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去。收信方收到密文后,若想解读原文,则需要使用加密用过的密钥及相同算法的逆算法对密文进行解密,才能使其恢复成可读明文。在对称加密算法中,使用的密钥只有一个,发收信双方都使用这个密钥对数据进行加密和解密,这就要求解密方事先必须知道加密密钥。
-
- 2.非对称性密钥加密
非对称加密算法需要两个密钥:公开密钥和私有密钥。公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。
-
- 3.证书密钥加密
服务器的开发者携带公开密钥,像数字证书认证机构提出公开密钥的申请,数字证书机构在认清申请者的身份,审核通过后,会对开发者申请的公开密钥做数字签名,然后分配这个已签名的公开密钥,并将密钥放在证书里面,绑定在一起
服务器将这份数字证书发送给客户端,因为客户端也认可证书机构,客户端可以通过数字证书中的数字签名来验证公钥的真伪,来确保服务器传过来的公开密钥是真实的。一般情况下,证书的数字签名是很难被伪造的,这取决于认证机构的公信力,以但确认信息无误之后,客户端就会通过公钥对报文进行加密发送,服务器接收到以后用自己的私钥进行解密。
三、入门案例
入门准备:
request模块
作用
python中原生的一款基于网络请求的模块,功能非常强大,简单便捷,效率极高
模拟浏览器发出请求
使用(request模块的编码流程)
-- step1:指定url
-- step2:UA伪装
-- step3:发起请求
-- step4:获取响应数据
-- step5:持久化存储
环境安装
pip install requests
我这里使用的PyCharm编辑器,可以通过软件安装request依赖包,setting->Project->Python Interpreter->左下角”+“->搜索requests,添加
3.1 爬取搜狗首页的页面数据
import requests
if __name__ == "__main__":
# step1: 指定url
url = "https://www.sogou.com"
# step2: 发起请求。get方法会发挥一个响应对象
response = requests.get(url=url)
# step3: 获取响应数据.text返回的是字符串形式的响应数据
page_text = response.text
print(page_text)
# step4: 持久化存储
with open("./sogou.html", 'w', encoding='utf-8') as fp:
fp.write(page_text)
print("爬取数据结束!!!")
3.2 爬取搜狗指定词条对应的搜索结果页面(简易网页采集器)
import requests
if __name__ == "__main__":
# UA伪装:将对应的User-Agent封装到一个字典中
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 '
}
url = "https://www.sogou.com/web"
# 处理url中携带的参数,封装到字典中去
key = input('enter a word: ')
param = {
'query': key
}
# 对指定的url发起的请求对应的url是携带参数的,并且请求过程中处理了参数
response = requests.get(url=url, params=param, headers=headers)
# 获取页面内容
page_text = response.text
fileName = key+".html"
with open(fileName, 'w', encoding='utf-8') as fp:
fp.write(page_text)
print(fileName, '保存成功!!!')
3.3 破解百度翻译,获取想要的翻译结果
import requests
import json
if __name__ == "__main__":
# step1: 指定url
post_url = 'https://fanyi.baidu.com/sug'
# step2: 进行UA伪装
# 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 '
}
# step3:post请求参数处理(同get方式一样)
data = {
'kw': 'dog'
}
# step4:请求发送
response = requests.post(url=post_url,data=data,)
# step5:获取响应数据:json()方法返回的是obj(如果确认响应数据是json类型的,才可以使用json()方法)
dic_obj = response.json()
fp = open('./dog.json','w',encoding='utf-8')
json.dump(dic_obj,fp,ensure_ascii=False)
print('保存成功!!!')
3.4 练习四:爬取豆瓣电影分类排行榜 https://movie.douban.com/ 中的电影详情数据
import requests
import json
if __name__ == "__main__":
# step1:指定url
url = 'https://movie.douban.com/j/chart/top_list'
# step2:处理get请求中的参数
param = {
'type':'24',
'interval_id': '100:90',
'action':'',
'start':'1', # 查询开始的下标值
'limit':'20' # 查询的数据个数
}
# step3: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 '
}
# step4:发起请求
response = requests.get(url=url,params=param,headers=headers)
list_data = response.json()
fp = open('./douban.json', 'w', encoding='utf-8')
json.dump(list_data, fp=fp, ensure_ascii=False)
print('爬取结束!!!')
3.5 练习五:爬取肯德基餐厅查询http://www.kfc.com.cn/kfccda/storelist/index.aspx中指定的餐厅数据
注意:如果是局部刷新,即ajax请求,需要按F12查看网络抓包情况,获取响应的请求参数
import requests
import json
if __name__ == "__main__":
# 1.指定url
url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword'
# 2.处理post请求参数
keyword = input('enter a site:')
dic_data = {
'cname':'',
'pid':'',
'keyword': keyword,
'pageIndex': '1',
'pageSize': '10'
}
# 3.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 '
}
# 4.发起请求
response = requests.post(url=url, data=dic_data, headers=headers)
# 5获取响应数据
result = response.json()
# 6.持久化存储
fp = open('./kfc.json','w',encoding='utf-8')
json.dump(result,fp=fp,ensure_ascii=False)
print('爬取结束!!!')
四、综合练习
需求: 爬取国家药品监督管理总局中基于中华人民共和国化妆品生产许可证相关数据http://scxk.nmpa.gov.cn:81/xk/
-
动态加载数据
-
首页中对应的企业信息数据是通过ajax动态请求到的。
http://scxk.nmpa.gov.cn:81/xk/itownet/portal/dzpz.jsp?id=e6c1aa332b274282b04659a6ea30430a
http://scxk.nmpa.gov.cn/xk/itownet/portal/dzpz.jsp?id=f63f61fe04684c46a016a45eac8754fe
通过对详情页url的观察发现:
url的域名都是一样的,只有携带的参数(id)不一样
id值可以从首页对应的ajax请求到的json串中获取
域名和id值拼接处一个完整的企业对应的详情页的url
详情页的企业详情数据也是动态加载出来的
http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsById
http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsById
观察后发现:
所有的post请求的url都是一样的,只有参数id值是不同。
如果我们可以批量获取多家企业的id后,就可以将id和url形成一个完整的详情页对应详情数据的ajax请求的url
# -*- coding = utf-8 -*-
# @Time: 2021/2/25 9:45
# @Author: Poison
# @File: 爬取爬取国家药品监督管理总局中基于中华人民共和国化妆品生产许可证相关数据.py
# @Software: PyCharm
import requests
import json
if __name__ == "__main__":
# -*- 批量获取不同企业的id值 -*-
# step1:指定url
url = 'http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsList'
# step2:处理post请求参数
keyword = input('enter a key:')
dic_data = {
'n': 'true',
'page': '1',
'pageSize': '100',
'productName': '广东',
'conditionType': '2',
'applyname': '',
'applysn': ''
}
# step3:进行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 '
}
# step4:发起请求
response = requests.post(url=url, data=dic_data, headers=headers)
# step5:获取响应数据
res_data = response.json()
print("企业id爬取结束!!!")
# step6:遍历企业数据,封装id数组
id_list = []
for dic in res_data['list']:
id_list.append(dic['ID'])
# -*- 获取企业详情数据 -*-
company_detail = []
# step7:指定详情页请求url
detail_url = 'http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsById'
# step8:处理请求参数
for id in id_list:
dic_data = {
'id': id
}
detail_data = requests.post(url=detail_url, headers=headers, data=dic_data).json()
company_detail.append(detail_data)
# step9:持久化获取的详情数据
fp = open('./company.json', 'w', encoding='utf-8')
json.dump(company_detail, fp=fp, ensure_ascii=False)
print('企业详情爬取结束!!!')