python网络爬虫
静态网页爬取概述
静态网页介绍
- 在网站设计中,纯粹HTML(标准通用标记语言下的一个应用)格式的网页通常被称为“静态网页”,静态网页是标准的HTML文件,它的文件扩展名是.htm、.html,可以包含文本、图像、声音、FLASH动画、客户端脚本和ActiveX控件及JAVA小程序等。(无法实现交互功能)
- 静态网页是网站建设的基础,早期的网站一般都是由静态网页制作的。静态网页是相对于动态网页而言,是指没有后台数据库、不含程序和不可交互的网页。动态网页有数据传递的过程,实时更新。静态网页相对于动态网页加载速度更快。
简单静态网页爬取
-
爬虫进本流程
(1) 发起请求:通过HTTP库向目标站点发起请求,即发送一个Request,请求可以包含额外的headers等信息,等待服务器响应。
(2) 获取响应内容:如果服务器能正常响应,会得到一个Response,Response的内容便是所要获取的页面内容,类型可能有HTML,Json字符串,二进制数据(如图片视频)等类型。
(3) 解析内容:得到的内容可能是HTML,可以用正则表达式、网页解析库进行解析。可能是Json,可以直接转为Json对象解析,可能是二进制数据,可以做保存或者进一步的处理。
(4) 保存数据:保存形式多样,可以存为文本,也可以保存至数据库,或者保存特定格式的文件。
实现HTTP请求
1.使用urllib3库实现
许多Python的原生系统已经开始使用urllib3库,其提供了很多python标准库里所没有的重要特性。
连接特性 | 连接特性 |
---|---|
线程安全 | 管理连接池 |
客户端SSL∕TLS验证 | 使用分部编码上传文件 |
协助处理重复请求和HTTP重定位 | 支持压缩编码 |
支持HTTP和SOCKS代理 | 测试覆盖率达到100% |
(1)生成请求
通过request方法即可创建一个请求,该方法返回一个HTTP响应对象。Reques语法格式如下。
参数 | 说明 |
---|---|
method | 接收string。表示请求的类型,如“GET”、“HEAD”、“DELETE”等。无默认值 |
url | 接收string。表示字符串形式的网址。无默认值 |
field | 接收dict。表示请求类型所带的参数。默认为None |
headers | 接收dict。表示请求头所带参数。默认为None |
**urlopen_kw | 接收dict或其他Python中的类型的数据。依据具体需要及请求的类型可添加的参数,通常参数赋值为字典类型或为具体数据。无默认值 |
import urllib3
http = urllib3.PoolManager()#urllib3必须生成一个实例才能进行request请求
request = http.request('GET',
url = 'https://blog.csdn.net/m0_51877411/article/details/116208871?spm=1001.2014.3001.5501')
(2)请求头处理
在request方法中,如果需要传入headers参数,可通过定义一个字典类型实现。定义一个包含User-Agent信息的字典,使用浏览器为火狐和chrome浏览器,操作系统为“Windows NT 6.1; Win64; x64”,向网站添加链接描述发送带headers参数的GET请求,hearders参数为定义的User-Agent字典。
import urllib3
http = urllib3.PoolManager()#urllib3必须生成一个实例才能进行request请求
head = {'User-Agent':'Windows NT 6.1: Win64: x64'}
http.request('GET',
url = 'https://blog.csdn.net/m0_51877411/article/details/116208871?spm=1001.2014.3001.5501',
headers=head)
(3)Timeout设置
为防止因为网络不稳定、服务器不稳定等问题造成连接不稳定时的丢包,可以在请求中增加timeout参数设置,通常为浮点数。依据不同需求,timeout参数提供多种设置方法,可直接在URL后设置该次请求的全部timeout参数,也可分别设置该次请求的连接与读取timeout参数,在PoolManager实例中设置timeout参数可应用至该实例的全部请求中。
重定向(Redirect)就是通过各种方法将各种网络请求重新定个方向转到其它位置(如:网页重定向、域名的重定向、路由选择的变化也是对数据报文经由路径的一种重定向)。
- 方法一直接在url网址后添加
import urllib3
http = urllib3.PoolManager()#urllib3必须生成一个实例才能进行request请求
head = {'User-Agent':'Windows NT 6.1: Win64: x64'}
http.request('GET',
url = 'https://blog.csdn.net/m0_51877411/article/details/116208871?spm=1001.2014.3001.5501',
timeout=3.0,
headers=head)#超时超过三秒就终止
- 方法二 使用urllib3内置函数分别设置连接和读取参数
import urllib3
http = urllib3.PoolManager()#urllib3必须生成一个实例才能进行request请求
head = {'User-Agent':'Windows NT 6.1: Win64: x64'}
http.request('GET',
url = 'https://blog.csdn.net/m0_51877411/article/details/116208871?spm=1001.2014.3001.5501',
timeout=urllib3.Timeout(connect=1.0,read=2.0),
headers=head)#连接超过一秒或读取超过两秒就终止
- 方法三在设置好的PoolManager实例里进行设置
import urllib3
http = urllib3.PoolManager(timeout=4.0)
head = {'User-Agent':'Windows NT 6.1: Win64: x64'}
http.request('GET',
url = 'https://blog.csdn.net/m0_51877411/article/details/116208871?spm=1001.2014.3001.5501',
headers=head)
(4)请求重试设置
urllib3库可以通过设置retries参数对重试进行控制(超时重试)。默认进行3次请求重试,并进行3次重定向。自定义重试次数通过赋值一个整型给retries参数实现,可通过定义retries实例来定制请求重试次数及重定向次数。若需要同时关闭请求重试及重定向则可以将retries参数赋值为False,仅关闭重定向则将redirect参数赋值为False。与Timeout设置类似,可以在PoolManager实例中设置retries参数控制全部该实例下的请求重试策略。
- 方法一从实例的内置函数进行设置
import urllib3
http = urllib3.PoolManager(timeout=4.0,retries=10)#重试十次
head = {'User-Agent':'Windows NT 6.1: Win64: x64'}
http.request('GET',
url = 'https://blog.csdn.net/m0_51877411/article/details/116208871?spm=1001.2014.3001.5501',
headers=head)
- 方法二在request函数设置参数
http.request('GET',
url = 'https://blog.csdn.net/m0_51877411/article/details/116208871?spm=1001.2014.3001.5501',
headers=head,
retries=10)
(5)生成完整HTTP请求
使用urllib3库实现生成一个完整的请求,该请求应当包含链接、请求头、超时时间和重试次数设置。
User-Agent参数设置可在网页开发者工具(F12)进行查找。
按F12打开开发者工具,从Network中刷新查看参数
import urllib3
#发送请求头的实例
http = urllib3.PoolManager()
#网址
url = 'https://blog.csdn.net/m0_51877411/article/details/116208871?spm=1001.2014.3001.5501'
#请求头
head = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36 Edg/90.0.818.46'}
#超时时间的设置
time = urllib3.Timeout(connect=1.0,read=3.0)
#重试次数和重定向次数设置
request = http.request('GET', url=url ,headers=head, timeout=time, retries=5, redirect=4)
此时就可以生成完整的HTTP请求
接下来可以打印一下服务器响应码和响应实体
print('服务器响应码:', request.status)
print('响应实体:', request.data)
可以发现中文全部变成\x的编码方式
可以转换编码方式decode()
print('服务器响应码:', request.status)
print('响应实体:', request.data.decode('utf-8'))
此时中文可正常显示
可从网站源代码meta标签下查看编码方式
2.使用requests库实现HTTP请求
requests库是一个原生的HTTP库,比urllib3库更为容易使用。requests库发送原生的HTTP 1.1请求,无需手动为URL添加查询字串,也不需要对POST数据进行表单编码。相对于urllib3库,requests库拥有完全自动化Keep-alive和HTTP连接池的功能(因此不需要去手动给url进行查询字数的添加以及post数据进行表达编码,可以直接通过get方法获取响应实体)。requests库包含的特性如下。
连接特性 | 连接特性 | 连接特性 |
---|---|---|
Keep-Alive&连接池 | 基本∕摘要式的身份认证 | 文件分块上传 |
国际化域名和URL | 优雅的key∕value Cookie | 流下载 |
带持久Cookie的会话 | 自动解压 | 连接超时 |
浏览器式的SSL认证 | Unicode响应体 | 分块请求 |
自动内容解码 | HTTP(S)代理支持 | 支持.netrc |
- 使用requests库实现
-
生成请求
requests库生成请求的代码非常便利,其使用的request方法的语法格式如下。
request方法常用的参数及其说明如下。
参数 | 说明 |
---|---|
method | 接收string。表示请求的类型,如“GET”、“HEAD”、“DELETE”等。无默认值 |
url | 接收string。表示字符串形式的网址。无默认值 |
**kwargs | 接收dict或其他Python中的类型的数据。依据具体需要及请求的类型可添加的参数,通常参数赋值为字典类型或为具体数据 |
import requests
url = 'https://edu.tipdm.org/course/1749/task/42885/show'
rqq = requests.get(url)
print('响应码:',rqq.status_code)
print('编码方式:',rqq.encoding)
print('请求头:',rqq.headers)
print('响应实体:',rqq.content)
print('响应实体:',rqq.text)
此时可以发现中文编码以\x方式出现
content()和text()比较
print('响应实体:',rqq.content[:40])
print('响应实体:',rqq.text[:40])#打印前四十行
最后返回的字符串类型有所不同
2. 查看状态码与编码
- 需要注意的是,当requests库猜测错时,需要手动指定encoding编码,避免返回的网页内容解析出现乱码。
- chardet库使用detect方法检测给定字符串的编码,detect方法常用的参数及其说明如下。
参数 | 说明 |
---|---|
byte_str | 接收string。表示需要检测编码的字符串。无默认值 |
import requests
url = 'https://edu.tipdm.org/course/1749/task/42885/show'
rqq = requests.get(url)
rqq.encoding = 'utf-8'
print('响应实体:',rqq.text)
此时编码方式转换成中文编码正常显示
但content()仍以乱码形式出现
修改content()中文乱码方式
- 手动指定的方法并不灵活,无法自适应对应爬取过程中不同网页的编码,而使用chardet库比较简便灵活,chardet库是一个非常优秀的字符串∕文件编码检测模块。
import chardet
chardet.detect(rqq.content)#需要输入为字节型数据的content,如果输入text会报错
>>>import chardet
chardet.detect(rqq.content)#需要输入为字节型数据的content,如果输入text会报错
import chardet
chardet.detect(rqq.content)#需要输入为字节型数据的content,如果输入text会报错
>>>{'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}
-
请求头与响应头处理
requests库中对请求头的处理与urllib3库类似,也使用headers参数在GET请求中上传参数,参数形式为字典。使用headers属性即可查看服务器返回的响应头,通常响应头返回的结果会与上传的请求参数对应。
import requests
url = 'https://edu.tipdm.org/course/1749/task/42885/show'
head = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36 Edg/90.0.818.51'}
rqq = requests.get(url, headers=head)
rqq.headers
-
Timeout设置
为避免因等待服务器响应造成程序永久失去响应,通常需要给程序设置一个时间作为限制,超过该时间后程序将会自动停止等待。在requests库中通过设置timeout这个参数实现,超过该参数设定的秒数后,程序会停止等待。
import requests
url = 'https://edu.tipdm.org/course/1749/task/42885/show'
head = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36 Edg/90.0.818.51'}
rqq = requests.get(url, headers=head,timeout=2.0)
rqq.headers
-
生成完整HTTP请求
使用requests库的request方法向网站“http://www.tipdm.com/tipdm/index.html”发送一个完整的GET请求,该请求包含链接、请求头、响应头、超时时间和状态码,并且编码应正确设置。