目录

  • 网络库urllib
    • request
      • 发送GET请求
      • 发送POST请求
      • 请求超时处理
      • 爬虫伪装
      • 代理
      • 获取Cookie
    • Parse
      • 中文的编码与解码
      • quote与unquote
      • URL解析
      • 连接URL
      • 参数转换(parse_qs与parse_qsl)
    • Robots协议
      • Robots协议的定义规则
      • Robots协议的解析
    • error
      • HTTPError

网络库urllib

urllib库是Python3内置的HTTP请求库,不需要单独安装,默认下载的Python就已经包含了该库。

urllib库有4个模块:

  1. request:最基本的HTTP请求模块,可以用法发送HTTP请求,并接收服务器的响应数据,这个过程就像在浏览器地址栏输入URL一样。
  2. parse:工具模块,提供了很多处理URL的API,如拆分、解析、合并等。
  3. robotparser:用来识别网站的robots.txt文件,然后判断哪些网站可以抓取,哪些不能抓取。
  4. error:异常处理。如果出现请求错误,可以捕获这些异常,然后根据代码的需要,进行处理。

下面,我们来分别介绍urllib库这4个模块。

request

request模块,包含发送请求,获得响应,Cookie,代理等相关API。这里,我们分别来介绍其使用的方式。

发送GET请求

首先,我们一般进行爬虫程序编写时,开始都需要发送请求,然后获得响应进行处理。比如通过GET请求获取网页源代码,示例如下:

import urllib.requestresponse=urllib.request.urlopen("https://www.csdn.net/")
print(response.read().decode("UTF-8"))

如上面代码所示,运行之后,我们会得到网页html源代码。

这里response是一个HTTPResponse对象,调用它多种方法及其属性,就可以进行多样的处理。

比如,我们这里来获取CSDN首页,调用其属性及其方法,示例如下:

import urllib.requestresponse = urllib.request.urlopen("https://www.csdn.net/")
print("status:", response.status, "  msg:", response.msg, "  version:", response.version)
print(response.getheaders())

这里,我们输出了CSDN首页的响应状态码,响应消息以及HTTP版本的属性,同时也打印其完整的响应头信息。

发送POST请求

默认request.urlopen()函数发送的GET请求,如果需要发送POST请求,我们需要使用data命令参数,该参数类型是bytes。示例代码如下:

import urllib.request
import urllib.parsedata = bytes(urllib.parse.urlencode({'username': 'name', 'age': '123456'}), encoding="UTF-8")
response = urllib.request.urlopen("http://httpbin.org/post", data=data)
print(response.read().decode("UTF-8"))

运行之后,如果请求成功就会返回一大堆字符串数据。

请求超时处理

在实际的爬虫项目中,我们都需要考虑一个关键的问题,那就是请求超时。如果请求网址因为长时间没有响应,那么卡在这里往往浪费大量的资源。

所以,我们需要设置一个超时时间,如果在限定的时间没有响应,就应该重新抓取,或者不在抓取。示例代码如下:

import urllib.request
import urllib.parse
import urllib.error
import socketdata = bytes(urllib.parse.urlencode({'username': 'name', 'age': '123456'}), encoding="UTF-8")
try:response = urllib.request.urlopen("http://httpbin.org/post", data=data, timeout=0.1)print(response.read().decode("UTF-8"))
except urllib.error.URLError as e:if isinstance(e.reason,socket.timeout):print("超时处理")
finally:print("继续爬虫的工作")

爬虫伪装

现在只要是知名的网站,都具有定义的防爬虫技术。所以,我们在开发爬虫程序时,需要将自己的请求伪装成浏览器。

不过,urlopen()并没有header请求头参数,我们需要使用request.Request()进行构造请求,示例代码如下:

import urllib.request
import urllib.parsedata = bytes(urllib.parse.urlencode({'username': 'name', 'age': '123456'}), encoding="UTF-8")
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
req = urllib.request.Request("http://httpbin.org/post", data=data, headers=headers)
response = urllib.request.urlopen(req)
print(response.read().decode("UTF-8"))

这里,我们将爬虫程序伪装成从火狐浏览器进行的请求。

当然,Request类还有许多其他的信息,下表是博主列出来供读者参考使用的。

参数 意义
url 用于发送请求的URl,必选参数(除这个参数之外,其他参数可选)
data 要提交的表单数据,必须是bytes类型
headers 请求头
origin_req_host 请求方的host名称或IP地址
unverifiable 表示这个请求是否是无法验证的,默认是False,主要是说明用户没有足够的权限来选择接收这个请求的结果。举个例子,请求一个HTML的图像,但没有自动抓取图像的权限,这个时候该参数为True
method 用来指定是什么请求,比如GET,POST,PUT等,如果指定了data,默认就是POST请求

需要注意的是最后一个参数method,如果你在程序中,即指定了请求是GET,同时也有data表单数据,那么默认表单不会提交给服务器。

代理

其实,服务器除了根据请求头进行判断是否为爬虫之外,最简单判别爬虫的方式,就是判断是否是同一个IP短时间大量访问。

如果同一个IP短时间大量访问,那么可以直接判别为爬虫程序。而这个时候,我们可以通过代理进行伪装。当然,使用代理时应该不断更换代理服务器。

示例代码如下:

import urllib.error
from urllib.request import ProxyHandler, build_openerproxy_handler = ProxyHandler({'http': 'http://183.47.138.80:8888','http': 'http://125.78.226.217:8888'
})
opener = build_opener(proxy_handler)
try:response = opener.open('https://www.csdn.net/')print(response.read().decode('UTF-8'))
except urllib.error.URLError as e:print(e.reason)

运行之后,与前文一样返回CSDN首页的源代码。不过,需要注意的是,博主在写博客时,这个代码IP是有效的,但如果你读到这篇博文,可能已经失效了,你需要自己取找免费的代理服务器取测试。

获取Cookie

一般来说,当我们使用爬虫登录网站之后,会使用服务器返回的Cookie进行操作,有了这个Cookie,服务器就知道我们已经登录过。

那么如果获取Cookie数据呢?示例如下:

import urllib.error
from urllib.request import ProxyHandler
import http.cookiejarcookie = http.cookiejar.CookieJar()
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
try:response = opener.open('https://www.csdn.net/')for item in cookie:print("name=", item.name, "  value=", item.value)
except urllib.error.URLError as e:print(e.reason)

如上面代码所示,我们可以通过http.cookiejar库进行操作,这里会返回cookie的键值对,并输出打印,效果如下:


如果本身网站的Cookie时效比较长的话,那么一次爬虫之后,我们可以将其保存在使用,这个时候会用到MozillaCookieJar类与LWPCookieJar类。

这2个类会在获取Cookie的同一时间,将Cookie分别保存为Mozilla浏览器格式和libwww-perl(LWP)格式。示例代码如下:

import urllib.error
from urllib.request import ProxyHandler
import http.cookiejarcookie = http.cookiejar.MozillaCookieJar('cookies.txt')
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
try:response = opener.open('https://www.csdn.net/')cookie.save(ignore_discard=True,ignore_expires=True)
except urllib.error.URLError as e:print(e.reason)

运行之后,会生成一个cookies.txt文件,具体内容如下:

而LWPCookieJar类的使用方式与上面MozillaCookieJar类似,这里不在赘述。至于读取通过cookie.load()方法进行加载Cookie。

Parse

在实际的爬虫处理中,我们经常会遇到各种的编码问题。而这些问题就可以通过Parse进行解决处理。

中文的编码与解码

比如,在某些网址的请求头中,有些网站请求头会含有中文。但默认不进行任何处理肯定会报UnicodeEncodeError错误。

读者可以通过上面的代码,在headers字典中添加一个键值对,值是中文试试。下面,我们需要对其进行编码,示例如下:

import urllib.parse
import base64value = urllib.parse.urlencode({'name': '安踏'})
print("编码后的中文:", value)
print("解码后的中文:", urllib.parse.unquote(value))
#base64编码与解码
base64Value=base64.b64encode(bytes('学习网络urllib库',encoding="UTF-8"))
print("编码后的中文:", base64Value)
print("解码后的中文:", str(base64.b64decode(base64Value),"UTF-8"))

运行之后,效果如下:

需要注意的是,urlencode只能对url参数进行编码,比如这里对headers请求头进行了编码。而网站中的数据,有的是通过base64进行编码的,这个时候,我们也需要掌握base64的解码与编码。

quote与unquote

quote函数也是一个编码函数,但它与urlencode不同,urlencode只能对URL进行编码。而quote可以给任意字符串进行编码。

至于unquote是编码的逆过程(解码),示例如下:

from urllib.parse import quote, unquoteurl = 'https://www.baidu.com/s?wd=' + quote("王者荣耀")
print(url)
url = unquote(url)
print(url)

运行之后,效果如下:

URL解析

在前面介绍的时候,我们也说了parse模块可以分解,分析,合并URL。下面,我们来通过这些函数,举一些列子,读者就会明白了。

from urllib import parseurl = 'https://www.csdn.net/'
split_result=parse.urlsplit(url);
print(split_result)
result = parse.urlparse(url)
print('scheme:', result.scheme)  # 网络协议
print('netloc:', result.netloc)  # 域名
print('path:', result.path)  # 文件存放路径
print('query:', result.query)  # 查询字符
print('fragment:', result.fragment)  # 拆分文档中的特殊猫

运行之后,效果如下:

连接URL

对于URL来说,有时候我们需要将URL的多个部分进行组合。比如,我们在爬取某一个网站下图片时,其默认的前部分基本都相同,可能只是ID不同。

那么这个时候,我们需要将前部分URL与ID进行拼接。示例代码如下:

import urllib.parseprint(urllib.parse.urljoin('https://blog.csdn.net','liyuanjinglyj'))
print(urllib.parse.urljoin('https://blog.csdn.net','https://www.baidu.com'))
print(urllib.parse.urljoin('https://blog.csdn.net','index.html'))
print(urllib.parse.urljoin('https://blog.csdn.net/index.php','?name=30'))

运行之后,效果如下:


urljoin的使用规则:第1个参数是base_url,是一个基URL,只能设置scheme、netloc和path,第2个参数是url。

如果第2个参数不是一个完整的URL,会将第2个参数的值加到第1个参数的后面,自动添加斜杠"/”。

如果第2个参数是一个完整的URL,那么直接返回第2个URL。

参数转换(parse_qs与parse_qsl)

parse_qs函数将多个参数拆成字典的形式,key是参数名,value是参数值。

而parse_qsl函数返回一个列表,每个元素是一个包含2个元素值的元组,第1个元素表示key,第2个元素表示value。

示例如下:

from urllib.parse import parse_qs, parse_qslquery = "name=李元静&age=29"
print(parse_qs(query))
print(parse_qsl(query))

运行之后,效果如下:

2个函数仅返回的参数形式不同,内容基本都是匹配的。同时,它们2个函数不管对什么类型,转换结果都是字符串。

Robots协议

Robots协议也称为爬虫协议、机器人协议,它的全名是网络爬虫排除标准(Robots Exclusing Protocol)。

用来告诉爬虫和搜索引擎哪些页面可以抓取,哪些不可以抓取。该协议通常放在一个名为robots.txt的文本文件中,它位于网站的根目录下。

特别注意,robots.txt文件仅仅是为了告诉开发中哪些数据可以抓取,哪些数据不可以,并不能阻止开发中进行爬虫操作。但作为一个有良知的程序员,应尽量尊重这些规则。

Robots协议的定义规则

robots.txt的文本文件一般有3个值:

  1. User-agent:如果它为*,表示对所有爬虫有效
  2. Disallow:哪个目录下的资源不能抓取,比如Disallow:/index/,那么禁止爬取index文件中的所有资源。如果为/,表示该网站都不能抓取。
  3. Allow:表示哪个目录下的资源可以抓取。比如Allow:/,表示所有网站都可以抓取。值与Disallow一样,只是反意义。

当然,User-agent还可以禁止某些爬虫抓取,比如禁止百度爬虫抓取:User-agent:BaiduSpider。常用的爬虫名如下表:

爬虫名称 搜索引擎
Googlebot 谷歌
360Spider 360搜索
Bingbot 必应
BaiduSpider 百度

Robots协议的解析

当然,我们获取Robots协议,肯定是为了获取哪些资源不可爬。但是,直接通过字符串进行解析虽然也能完成,不过稍微复杂了点。

而urllib库的robotparser模块提供了相应的API进行解析,也就是RobotFileParser类。示例如下:

from urllib.robotparser import RobotFileParser
#一种解析方式
robot = RobotFileParser()
robot.set_url('https://www.csdn.net/robots.txt')
robot.read()
print(robot.can_fetch('*', 'https://blog.csdn.net/rank/list'))#另一种解析方式
robot = RobotFileParser('https://www.csdn.net/robots.txt')
print(robot.can_fetch('*', 'https://blog.csdn.net/rank/list'))

这里,can_fetch方法用来判断该网址根据Robots协议是否可以抓取。这里判断的是CSDN排行榜能否抓取,返回了True。

error

异常处理在上面的代码中,我们已经用过了。比如在请求超时的讲解之中,我们用到了URLError。但是它还有一个子类HTTPError。

HTTPError

它主要用于HTTP请求错误的处理,比如400,404等错误。

HTTPError有3个重要的参数:

  1. code:服务器返回的状态码,如404等
  2. reason:返回错误的原因
  3. headers:返回请求头

不过,HTTPError不能捕获超时错误,如果你需要处理超时错误,那么只能通过URLError进行捕获。

Python爬虫:史上最详细的Python爬虫库urllib讲解,绝对经典,值得收藏相关推荐

  1. python导入同级包_python小课堂15 - 史上最详细的包和模块import讲解篇

    python小课堂15 - 史上最详细的包和模块import讲解篇 前言 在大量的代码设计中,我们不可能将所有代码都写在一个.py文件,所以有了包.模块,而为了代码可以重复利用(复用性),就有了类.函 ...

  2. python 引入同一路径的类_python小课堂15 - 史上最详细的包和模块import讲解篇

    python小课堂15 - 史上最详细的包和模块import讲解篇 前言 在大量的代码设计中,我们不可能将所有代码都写在一个.py文件,所以有了包.模块,而为了代码可以重复利用(复用性),就有了类.函 ...

  3. 【python小课堂专栏】python小课堂15 - 史上最详细的包和模块import讲解篇

    python小课堂15 - 史上最详细的包和模块import讲解篇 前言 在大量的代码设计中,我们不可能将所有代码都写在一个.py文件,所以有了包.模块,而为了代码可以重复利用(复用性),就有了类.函 ...

  4. python用什么来写模块-史上最详细的python模块讲解

    模块的概念你一定不会陌生吧,这是一个非常宽泛的概念,在各行各业都会用到.这里我们涉及的只是软件中的模块概念.说到模块,就得先了解下模块化程序设计的概念.(如果您对模块化程序设计的概念已经烂熟于心,尽可 ...

  5. python如何将图片打包进exe里_史上最详细的Python打包成exe文件教程

    打包成exe文件可以让python代码在没有python环境的条件下,依然能够运行,实在是码农们写追女朋友表白.情人节浪漫的必需品! 1.使用豆瓣镜像源下载: pyinstaller 有需要了解如何使 ...

  6. 史上最详细YOLOv5的predict.py逐句讲解

    代码为YOLOv5-v7.0 目录 前言 一.导入模块 二.parse_opt()函数 三.run()函数 四.main()函数 前言 YOLOv5-v7.0将分类脱离出来了.predict.py为分 ...

  7. Eclipse安装教程 ——史上最详细安装Java Python教程说明

                                                                Eclipse安装教程 --史上最详细安装Java&Python教程说明 ...

  8. python高分书籍推荐_史上最全的Python书排行榜|你想知道的都在这里

    原标题:史上最全的Python书排行榜|你想知道的都在这里 感谢关注天善智能,走好数据之路↑↑↑ 欢迎关注天善智能,我们是专注于商业智能BI,大数据,数据分析领域的垂直社区,学习,问答.求职一站式搞定 ...

  9. 玩转Python必备:史上最全的Python库,【值得收藏,事半功倍】

    库名称     简介 Chardet字符编码探测器,可以自动检测文本.网页.xml的编码. colorama主要用来给文本添加各种颜色,并且非常简单易用. Prettytable主要用于在终端或浏览器 ...

最新文章

  1. 【web】将一个jar包更改成war包
  2. idea 打开html有错误,Intellij IDEA + Tomcat 出现 HTTP status 404错误的解决办法
  3. 阿帕奇跨域_阿帕奇骆驼遇见Redis
  4. JAVA TCP通信练习
  5. 计算机编码中进制的区别,计算机中的进制和编码(转载)
  6. CStatic类的GDI双缓冲绘图
  7. 深入理解Flink ---- 系统内部消息传递的exactly once语义
  8. 计算机组成原理试题解析pdf,计算机组成原理试题集.pdf
  9. MAC电脑如何用苹果电脑微信版实现多开
  10. git强制覆盖master分支
  11. winserver 443端口被system占用_手机系统占用内存越来越大,是谁的锅?
  12. route 命令使用详解
  13. 网络分析仪测试线损_手把手教你用2端口网络分析仪进行阻抗调试分析--网络分析仪维修...
  14. 2023华为OD面试手撕代码经验分享
  15. 三基色PWM调光方法
  16. 字符串 Z 字形变换(Java)
  17. 本周推荐 | 基于 canvas 实现 H5 丝滑看图体验
  18. rockpi4b刷入安卓11镜像后跑不起来
  19. 【电路】电路与电子技术基础 课堂笔记 第1章 电路的基本概念及基本定律
  20. 计算机械产量定额,2020一造《计价》必会题,机械台班定额消耗量的计算!

热门文章

  1. HTML简约导航源码
  2. 用错错错错错错知知中算改改不不写一句富含哲理的话
  3. 辰视将携3D视觉技术及各领域解决方案参加华南工博会国际机器视觉展
  4. 勤奋,不足以让你过上好日子
  5. 一个基于C#实现的简易QQ农场
  6. Android之近场通信技术
  7. 联想文件服务器推荐配置,联想DS系列存储配置文档(非IBM DS系列)
  8. 抖音seo账号矩阵霸屏系统源码/账号矩阵系统搭建部署
  9. DXC Technology任命Ken Corless为产品与战略合作伙伴执行副总裁
  10. 利融网浅谈大数据在信用审核中的应用