天天看点

python网络爬虫 : 静态网页爬取python网络爬虫

python网络爬虫

静态网页爬取概述

静态网页介绍

  • 在网站设计中,纯粹HTML(标准通用标记语言下的一个应用)格式的网页通常被称为“静态网页”,静态网页是标准的HTML文件,它的文件扩展名是.htm、.html,可以包含文本、图像、声音、FLASH动画、客户端脚本和ActiveX控件及JAVA小程序等。(无法实现交互功能)
  • 静态网页是网站建设的基础,早期的网站一般都是由静态网页制作的。静态网页是相对于动态网页而言,是指没有后台数据库、不含程序和不可交互的网页。动态网页有数据传递的过程,实时更新。静态网页相对于动态网页加载速度更快。

简单静态网页爬取

  1. 爬虫进本流程

    (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的编码方式

python网络爬虫 : 静态网页爬取python网络爬虫

可以转换编码方式decode()

print('服务器响应码:', request.status)
print('响应实体:', request.data.decode('utf-8'))
           

此时中文可正常显示

python网络爬虫 : 静态网页爬取python网络爬虫

可从网站源代码meta标签下查看编码方式

python网络爬虫 : 静态网页爬取python网络爬虫

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库实现
  1. 生成请求

    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)
           
python网络爬虫 : 静态网页爬取python网络爬虫

此时可以发现中文编码以\x方式出现

content()和text()比较

print('响应实体:',rqq.content[:40])
print('响应实体:',rqq.text[:40])#打印前四十行
           
python网络爬虫 : 静态网页爬取python网络爬虫

最后返回的字符串类型有所不同

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)
           
python网络爬虫 : 静态网页爬取python网络爬虫

此时编码方式转换成中文编码正常显示

但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': ''}
           
  1. 请求头与响应头处理

    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
           
  1. 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
           
  1. 生成完整HTTP请求

    使用requests库的request方法向网站“http://www.tipdm.com/tipdm/index.html”发送一个完整的GET请求,该请求包含链接、请求头、响应头、超时时间和状态码,并且编码应正确设置。