爬虫
requests(模块)
scrapy框架
数据结构+算法
数据结构
链表和二叉树
算法
选择,冒泡,插入,希尔,快速,二分查找等
数据分析
机器学习
Anacanda
集成环境.是一个基于数据分析和机器学习的集成环境.
安装
1.安装路径中不可以出现中文和特殊符号
2.记得添加环境变量
查看是否安装成功:
打开终端:jupyter notebook指令,按下回车
jupyter
Anancanda提供的一个基于浏览器的可视化开发工具.
启动:打开终端:jupyter notebook
终端的默认路径就是你启动jupyter后对应页面的目录结构
cell:
code:编写代码,执行代码
注意:代码编写不分上下,代码执行分上下
markdowm:
编写笔记.可以使用html制定样式
快捷键
新建cell: a,b
删除cell:x
撤销:z
改变cell的模式
m:可以将code模式的cell切换成markdown模式的
y:反之
执行cell: shift+enter
打开帮助文档:shift+tab
什么是爬虫
就是通过编写程序模拟浏览器上网,然后让其去互联网上抓取数据的过程.
爬虫分类
1 通用爬虫
抓取一整张页面源码数据.
2 聚焦爬虫
建立在通用爬虫的基础之上.抓取页面中局部的数据.
3 增量式爬虫
监测网站数据更新的情况.将最新更新出来的数据进行爬取.
4 分布式爬虫
是作为提升爬虫爬取效率的终极武器.
反爬机制
门户网站会指定一些机制阻止爬虫进行其网站数据的爬取.
反反爬策略
爬虫就需要指定相关的策略去破解网站的反爬机制,从而爬取到对应的数据
第一个反爬机制:
robots协议:纯文本的协议,里面规定了什么能爬什么不能爬.
例如:https://www.baidu.com/robots.txt
requests
一个基于网络请求的模块
作用:用来模拟浏览器上网.
环境安装:pip install requests
requests编码流程
指定url
发起请求
获取响应数据
持久化存储
将搜狗首页的页面源码数据爬取
import requests
#1.指定url
url = 'https://www.sogou.com/'
#2.发起请求,get返回一个响应对象
response = requests.get(url=url)
#3.获取响应数据,text返回字符串形式的响应数据
page_text = response.text
print(page_text)
#4.持久化存储
with open('./sogou.html','w',encoding='utf-8') as fp:
fp.write(page_text)
实现一个简易网页采集器
参数动态化
动态的指定请求携带的请求参数
基于get/post方法中的params或者data参数实现
示例
url = 'https://www.sogou.com/web'
key = input('enter a word:')
#参数动态化
params = {
'query':key
}
response = requests.get(url=url,params=params)
page_text = response.text
fileName = key+'.html'
with open(fileName,'w',encoding='utf-8') as fp:
fp.write(page_text)
enter a word:人民币
上述代码有问题
没有爬取到正常的数据,页面数据显示异常访问请求
说明是异常的访问请求
只要不是浏览器发起的请求,网站的后台自动认为是爬虫程序则归属到异常请求中.
解决方法先了解第二个反扒机制
User-Agent:请求载体的身份标识
将爬虫的请求载体伪装成浏览器的
第二个反爬机制:UA检测
反反爬策略:UA伪装
url = 'https://www.sogou.com/web'
key = input('enter a word:')
#参数动态化
params = {
'query':key
}
#请求头伪装/篡改,添加请求头就可以进行改进了
headers = {
'User-Agent':"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"
}
response = requests.get(url=url,params=params,headers=headers)
page_text = response.text
fileName = key+'.html'
with open(fileName,'w',encoding='utf-8') as fp:
fp.write(page_text)
enter a word:人民币
爬取豆瓣电影的电影数据
分析:发现了滚轮下滑到底部回弹了,且页面刷新出了更多的电影数据
回弹:就是一个ajax请求,页面刷新出来的数据就是ajax请求到的数据
动态加载数据
如果你想要的数据不是通过浏览器地址栏里的url请求到的,则这些数据就是动态加载数据,也可以理解为是局部跟新,但是页面不跳转,
如何检测一个网站中你想要的数据是否为动态加载数据呢?
在抓包工具中进行局部搜索或者查看preview选项卡
注意:
对一个陌生的网站进行爬取前一定要检测你想要的数据是否为动态加载的,如果不是动态加载的,就直接在地址栏获取,如果是动态的就不能在地址栏加载
如何捕获动态加载的数据?
基于抓包工具进行全局搜索,找到url
局部是用来检测数据是不是动态加载的 ,全局是用来定位动态加载的数据包的
操作:
#这个地址不是浏览器上面的那个地址
url = 'https://movie.douban.com/j/chart/top_list'
params = {
'type': '13',
'interval_id': '100:90',
'action': '',
'start': 1,
'limit': 30,
}
headers = {
'User-Agent':"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"
}
response = requests.get(url=url,params=params,headers=headers)
json_data = response.json() #json()返回序列化好的对象
for dic in json_data:
title = dic['title']
score = dic['score']
print(title,score)
常用的抓包工具(主要是应用在移动端数据爬取)
fiddler
青花瓷
miteproxy
作用:可以拦截请求和响应
抓包工具就是一个代理服务器
代理服务器就是进行请求和响应的转发
https的加密方式:https://www.cnblogs.com/wupeiqi/articles/11647089.html
注意:页面不刷新的时候直接在地址栏获取,问号后面省略,写成参数
爬取北京所有的餐厅位置数据
url:http://www.kfc.com.cn/kfccda/storelist/index.aspx
url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword'
for page in range(1,8):
data = {
'cname':'' ,
'pid': '',
'keyword': '北京',
'pageIndex': str(page),
'pageSize': '10',
}
data_json = requests.post(url=url,headers=headers,data=data).json()
for dic in data_json['Table1']:
address = dic['addressDetail']
print(address)
爬取药监总局前五页企业的企业详情数据
url:http://scxk.nmpa.gov.cn:81/xk/
分析:
查看想要爬取的数据是否为动态加载
通过抓包工具发现爬取的数据是动态加载的,然后根据全局搜索可以定位到动态加载数据对应的数据包
从数据包中可以提取出
url:http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsById
请求方式:post
请求参数:id: 8c7be1437ddc4ff1bc8f29b1893390be
参数值是一个hash值(密文).需要注意查看该参数值是否为动态变化(每次请求对应的参数值不同)
多捕获几次该数据包,对应每一个数据包对应的id值是否一样
可以将提取到url进行请求发送捕获动态加载的数据
通过对另一家企业详情数据的捕获分析发现,不同的企业对应的请求参数id的值是不同的
id就表示企业的唯一标识
如果想要获取75家企业信息,必须获取75家企业不同的id值
如何获取不同企业的id
猜想企业id和企业名称进行了关联.然后在首页会有不同的企业名称数据.通过抓包去寻找企业名称对应的数据包定位企业id
从数据包中提取
url:http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsList
方式:post
参数:常态化参数
请求到的数据中就包含了企业id
main_url = 'http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsList'
url = 'http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsById'
for page in range(1,6):
data = {
'on': 'true',
'page': str(page),
'pageSize': '15',
'productName': '',
'conditionType': '1',
'applyname': '',
'applysn': '',
}
data_list = requests.post(url=main_url,headers=headers,data=data).json()['list']
for dic in data_list:
print('正在爬取一页的数据!')
_id = dic['ID']
data = {
'id':_id
}
json_data = requests.post(url=url,headers=headers,data=data).json()
print(json_data)
. . .
爬取店铺详情页数据
url:https://m.vmall.com/help/hnrstoreaddr.htm
#如果抓包工具里的请求参数直接给的是一个字典,则在post中使用json参数进行参数动态化
main_url = 'https://openapi.vmall.com/mcp/offlineshop/getShopList'
url = 'https://openapi.vmall.com/mcp/offlineshop/getShopById'
data = {"portal":2,"lang":"zh-CN","country":"CN","brand":1,"province":"北京","city":"北京","pageNo":1,"pageSize":20}
shop_list = requests.post(url=main_url,json=data).json()['shopInfos']
for dic in shop_list:
_id = dic['id']
params = {
'portal': '2',
'version': '10',
'country': 'CN',
'shopId': _id,
'lang': 'zh-CN',
}
shop_data = requests.get(url=url,headers=headers,params=params).json()
print(shop_data)
url:http://shop.slc0929.top/#/
突出了refere请求头
url = 'http://res.91kami.com/Index/Index?q=&p=1&size=20&showInStore=false'
headers = {
'User-Agent':"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36",
'Referer': 'http://shop.slc0929.top/'
}
data = {
'q': '',
'p': '1',
'size': '20',
'showInStore': 'false',
}
requests.post(url=url,headers=headers,data=data).json()
Referer: http://shop.slc0929.top/
出现下面的情况:
{'IsSuccess': False, 'Error_Code': -1, 'Error_Msg': '拒绝访问', 'AlertMsg': '拒绝访问'}
加'Referer'