一、爬虫的概念
1.爬虫的定义
- 如果我们把互联网比作一张大的蜘蛛网,那一台计算机上的数据便是蜘蛛网上的一个猎物,而爬虫程序就是一只小蜘蛛,沿着蜘蛛网抓取自己想要的猎物/数据。
- 下面就给出书面化的定义
网络爬虫也叫网络蜘蛛,它特指一类自动批量下载网络资源的程序,这是一个比较口语化的定义。- 更加专业和全面对的定义是:网络爬虫是伪装成客户端与服务端进行数据交互的程序.
2.爬虫的应用
(1)数据采集
大数据时代来临,数据就是核心,数据就是生产力,越来越多的企业开始注重收集用户数据,而爬虫技术是收集数据的一种重要手段。
比如:抓取微博评论(机器学习舆情监控)、抓取招聘网站的招聘信息(数据分析,挖掘)、百度新闻网站。
(2)模拟操作
爬虫也被广泛用于模拟用户操作,测试机器人,灌水机器人等。
(3)软件测试
爬虫之自动化测试虫师
(4)网络安全
短信轰炸web漏洞扫描
(5)搜索引擎
百度,谷歌等搜索引擎都是基于爬虫技术。
3.爬虫的合法性
- 在法律中是不被禁止
- 具有违法风险
- 善意爬虫 恶意爬虫
爬虫带来的风险可以体现在如下2方面:
- 爬虫干扰了被访问网站的正常运营
- 爬虫抓取了收到法律保护的特定类型的数据或信息
如何在使用编写爬虫的过程中避免进入局子的厄运呢?
- 时常的优化自己的程序,避免干扰被访问网站的正常运行
- 在使用,传播爬取到的数据时,审查抓取到的内容,如果发现了涉及到用户隐私商业机密等敏感内容需要及时停止爬取或传播
4.爬虫的分类
- 通用爬虫:
抓取系统重要组成部分。抓取的是一整张页面数据
。主要目的是将互联网的网页下载到本地,形成一个互联网内容的镜像备份。(但是有一个很大的问题就是它们具有很大的局限性:大部分内容没有用——不同的搜索目的,返回的内容相同!) - 聚焦爬虫:
是建立在通用爬虫的基础之上。抓取的是页面中特定的局部
内容。聚焦爬虫在实施页面抓取时会对内容进行处理筛选,尽量保证只抓取与需求相关的网页信息! - 增量式爬虫:
检测网站中数据更新的情况。只会抓取网站中最新更新
出来的数据。
5.爬虫的矛与盾
反爬机制
门户网站,可以通过制定相应的策略或者技术手段,防止爬虫程序进行网站数据的爬取。
反反爬策略
爬虫程序可以通过制定相关的策略或者技术手段,破解门户网站中具备的反爬机制,从而可以获取门户网站中相关的数据。
robots.txt协议:
君子协议:规定了网站中哪些数据可以被爬虫爬取哪些数据不可以被爬取。
csdn
6.爬虫的一般开发流程
①最简单的单一页面数据的爬取:
url——>发送请求,获取响应——>提取数据——>保存数据
②多页面数据的爬取:
发送请求,获取响应——>提取url地址,继续请求
- 模拟请求网页。模拟浏览器,打开目标网站。
- 获取数据。打开网站之后,就可以自动化的获取我们所需要的网站数据。
- 保存数据。拿到数据之后,需要持久化到本地文件或者数据库等存储设备中。
二、HTTP和HTTPS
网络爬虫是伪装成客户端与服务端进行数据交互的程序。那么,客户端和服务端该怎样进行数据交互呢?就像我们中国人用中文交流,说的中国的语法,我们可以正常沟通。客户端与服务端如果不统一一下,那不就乱套了,所以在网络传输方面产生了众多协议,HTTP就是其中一种。
目前互连网上90%的网络传输都是基于http协议
(补充: http协议是一个应用层协议)。
(注意:爬取想要的数据前,一定要明确其使用的是什么协议!虽然90%都是基于http协议,但是仍有10%采用的是其他的协议。
——比如:弹幕可能采取的是websocket协议 ! 这样的话,我们采取传统的爬虫就无法爬取到了。
1.http协议
(1)概念
官方概念
HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写是用于从万维网(WWW:World WideWeb )服务器传输超文本到本地浏览器的传送协议。
白话概念
HTTP协议就是服务器和客户端之间进行数据交相(互传输数据)的一种形式。我们可以将Server和Client进行拟人化,那么该协议就是Server和Cient这两兄弟间定的一种交沟通方式。大家都看过智取威虎山中杨子荣和土匪们之间说的黑话吧~
(2)常用请求头信息
- User-Agent:请求载体的身份标识
鼠标右击,点击检查,页面的右上角,点击网络后查看- Connection:请求完毕后,是断开连接还是保持连接
(3)常用响应头信息
- Content-Type:服务器响应回客户端的数据类型
2.https协议
- 安全的超文本传输协议
- 有数据加密
(1)加密方式
①对称秘钥加密
“共享密钥加密”,较为容易被拦截
②非对称秘钥加密
“非对称加密"使用的时候有两把锁,一把叫做**“私有密钥",一把是“公开密钥”**,使用非对象加密的加密方式的时候,服务器首先告诉客户端按照自己给定的公开密钥进行加密处理,客户端按照公开密钥加密以后,服务器接受到信息再通过自己的私有密钥进行解密,这样做的好处就是解密的钥匙根本就不会进行传输,因此也就避免了被挟持的风险。就算公开密钥被窃听者拿到了,它也很难进行解密,因为解密过程是对离散对数求值,这可不是轻而易举就能做到的事。
以下是非对称加密的原理图:
- 证书秘钥加密(https采用的方式)
三、requests模块基础
1.概念
requests模块:python中原生的一款基于网络请求的模块,功能非常强大,简单便捷,效率极高。
2.作用
模拟浏览器发请求。
3.如何使用
如何使用:(requests模块的编码流程)
- 指定url
- UA伪装
- 请求参数的处理
- 发起请求
- 获取响应数据
- 持久化存储
4.环境安装:
pip install requests
5.实战编码:
(1)实战编码需求:爬取搜狗首页的页面数据
import requests
if __name__ == "__main__":
# 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)
print("爬取数据结束!开心,爬出来的第一个数据")
获得一个存在本地的文件,可以查看源代码
运行代码html代码后即可构建和官网一样的搜狗页面
(2)实战巩固
response=requests.get(url=url,params=param,headers=headers)
需求1:爬取搜狗指定词条对应的搜索结果页面(简易网页采集器)
- UA:User-Agent(请求载体的身份标识)
- UA检测:门户网站的服务器会检测对应请求的载体身份标识,如果检测到请求的载体身份标识为某一款浏览器,说明该请求是一个正常的请求。但是,如果检测到请求的载体身份标识不是基于某一款浏览器的,则表示该请求为不正常的请求(爬虫),则服务器端就很有可能拒绝该次请求。
- UA伪装:让爬虫对应的请求载体身份标识伪装成某一款浏览器
import requests
if __name__ == "__main__":
#UA伪装:将对应的User-Agent封装到一个字典中
headers = {
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36'
}
url = 'https://www.sogou.com/web'
#处理url携带的参数:封装到字典中
kw = input('enter a word:')
param = {
'query':kw
}
#对指定的url发起的请求对应的url是携带参数的,并且请求过程中处理了参数
response = requests.get(url=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)
print(fileName,'保存成功!!!')
需求2:破解百度翻译
- post请求(携带了参数)
- 响应数据是一组json数据
定位数据包
响应数据是一组json数据
- 请求方法post
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/119.0.0.0 Safari/537.36 Edg/119.0.0.0'
}
#3.post请求参数处理(像get请求一致)
word=input('enter a word:')
data={
'kw':word
}
#4.发送请求
response=requests.post(url=post_url,data=data,headers=headers)
#5.获取响应数据:json()方法返回的是obj(如果确认响应数据是json类型的,才能用json)
dic_obj =response.json()
#进行持久化存储
filename=word+'.json'
fp = open(filename,'w',encoding='utf-8')
json.dump(dic_obj,fp=fp,ensure_ascii=False)
print("over!")
需求3:爬取豆瓣电影分类排行榜中的电影详情数据
本人学习时参考了以下博主的一篇文章——pycharm 中一键添加引号:http://t.csdnimg.cn/pVp5Z
import requests
import json
if __name__ == "__main__":
# 1.指定URL
count=int(input())
url = "https://movie.douban.com/j/chart/top_list"
param = {
'type': '24',
'interval_id': '100:90',
'action': '',
'start': count, #从库中第几部电影开始取
'limit': '20',#一次性取几个
}
# 2.进行UA伪装
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0'
}
response = requests.get(url=url, params=param,headers=headers)
list_date=response.json()
fp=open('./douban.json','w',encoding='utf-8')
json.dump(list_date,fp=fp,ensure_ascii=False)
print("over!!!")
json校验格式化工具:https://www.bejson.com/
作业:爬取肯德基餐厅中指定地点的餐厅数据
查询http://www.kfc.com.cn/kfccda/index.aspx
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import requests
import json
if __name__ == "__main__":
place=input("请输入你想查询的地点:")
# 1.指定URL
url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword'
# 2.UA伪装
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
params = {
'cname': '',
'pid': '',
'keyword': place,
'pageIndex':'1',
'pageSize': '1000',
}
# 3.产生响应
response = requests.post(url=url, params=params, headers=headers)
# 4.持久封装
place_data=response.json()
fp = open('./肯德基餐厅位置.json', 'w', encoding='utf-8')
json.dump(place_data, fp=fp, ensure_ascii=False)
print("over!!!")
需求4:爬取国家药品监督管理总局中基于中华人民共和国化妆品生产许可证相关数据
- 动态加载数据
- 首页中对应的企业信息数据是通过ajax动态请求到的。
http://125.35.6.84:81/xk/itownet/portal/dzpz.jspid=e6c1aa332b274282b04659a6ea30430a
http://125.35.6.84:81/xk/itownet/portal/dzpz.jsp?id=f63f61fe04684c46a016a45eac8754fe - 通过对详情页url的观察发现:
- url的域名都是一样的,只有携带的参数(id)不一样
- id值可以从首页对应的ajax请求到的json串中获取
- 域名和id值拼接处一个完整的企业对应的详情页的url
- 详情页的企业详情数据也是动态加载出来的
- http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkzsById
- http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkzsById
- 观察后发现:
- 所有的post请求的url都是一样的,只有参数id值是不同。
- 如果我们可以批量获取多家企业的id后,就可以将id和url形成一个完整的详情页对应详情数据的ajax请求的url