Urllib

urllib 包 包含以下几个模块:

  • urllib.request - 打开和读取 URL。
  • urllib.error - 包含 urllib.request 抛出的异常。
  • urllib.parse - 解析 URL。
  • urllib.robotparser - 解析 robots.txt 文件。

urllib.request

urllib.request 定义了一些打开 URL 的函数和类,包含授权验证、重定向、浏览器 cookies 等。

urllib.request 可以模拟浏览器的一个请求发起过程。

我们可以使用 urllib.request 的 urlopen 方法来打开一个 URL,语法格式如下:

1urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
  • url:url 地址。
  • data:发送到服务器的其他数据对象,默认为 None。
  • timeout:设置访问超时时间。
  • cafile 和 capath:cafile 为 CA 证书, capath 为 CA 证书的路径,使用 HTTPS 需要用到。
  • cadefault:已经被弃用。
  • context:ssl.SSLContext 类型,用来指定 SSL 设置。
1import urllib.request as req
2
3url = 'https://ys.mihoyo.com/'
4# 基本使用
5
6# 类型和方法
7# 模拟浏览器向服务器发送请求
8res1 = req.urlopen(url)
9
10# HTTPResponse 类型
11print(type(res1))
12
13# read 方法 返回的是字节形式的二进制数据
14# 参数为空返回全部字节,传人数字就读取多个字节
15# decode 为解码,把二进制的数据转换为某个编码类型的数据
16context1 = res1.read().decode('utf8')
17print(context1)
18
19# 读取一行
20context2 = res1.readline()
21print(context2)
22
23# 一行一行读取直到结束
24context3 = res1.readlines()
25print(context3)
26
27# 返回请求状态吗
28print(res1.getcode())
29# 返回url
30print(res1.geturl())
31# 返回状态信息
32print(res1.getheaders())
33
34# 下载
35# 参数1url是要下载的路径,第二个参数是文件的名称filename
36urllib = req.urlretrieve()

模拟头部信息

我们抓取网页一般需要对 headers(网页头信息)进行模拟,这时候需要使用到 urllib.request.Request 类:

1class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
  • url:url 地址。
  • data:发送到服务器的其他数据对象,默认为 None。
  • headers:HTTP 请求的头部信息,字典格式。
  • origin_req_host:请求的主机地址,IP 或域名。
  • unverifiable:很少用整个参数,用于设置网页是否需要验证,默认是 False。。
  • method:请求方法, 如 GET、POST、DELETE、PUT 等。
1import urllib.request
2import urllib.parse
3
4url = 'https://www.runoob.com/?s='  # 菜鸟教程搜索页面
5keyword = 'Python 教程'
6key_code = urllib.parse.quote(keyword)  # 对请求进行编码
7url_all = url+key_code
8header = {
9    'User-Agent':'Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
10}   #头部信息
11request = urllib.request.Request(url_all,headers=header)
12reponse = urllib.request.urlopen(request).read()
13
14fh = open("./urllib_test_runoob_search.html","wb")    # 将文件写入到当前目录中
15fh.write(reponse)
16fh.close()

请求对象的定制

UA 介绍:User Agent 中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统

及版本、CPU 类型、浏览器及版本。浏览器内核、浏览器渲染引擎、浏览器语言、浏览器插件等

urllib.parse

urllib.parse 用于解析 URL,格式如下:

1urllib.parse.urlparse(urlstring, scheme='', allow_fragments=True)

urlstring 为 字符串的 url 地址,scheme 为协议类型,

allow_fragments 参数为 false,则无法识别片段标识符。相反,它们被解析为路径,参数或查询组件的一部分,并 fragment 在返回值中设置为空字符串。

以上实例输出结果为:

完整内容如下:

属性 索引 值(如果不存在)
scheme 0 URL 协议 scheme 参数
netloc 1 网络位置部分 空字符串
path 2 分层路径 空字符串
params 3 最后路径元素的参数 空字符串
query 4 查询组件 空字符串
fragment 5 片段识别 空字符串
username 用户名 None
password 密码 None
hostname 主机名(小写) None
port 端口号为整数(如果存在) None

.quote()方法

将中文字符转换成 Unicode 编码格式

1kwd = urllib.parse.quote('原神')
2print(kwd) # %E5%8E%9F%E7%A5%9E

.urlencode()方法

可以将字典转化成 query 穿惨格式

1data = {
2    'wd':'原神'
3}
4data = urllib.parse.urlencode(data)
5print(data) # wd=%E5%8E%9F%E7%A5%9E

urllib.error

urllib.error 模块为 urllib.request 所引发的异常定义了异常类,基础异常类是 URLError。

urllib.error 包含了两个方法,URLError 和 HTTPError。

URLError 是 OSError 的一个子类,用于处理程序在遇到问题时会引发此异常(或其派生的异常),包含的属性 reason 为引发异常的原因。

HTTPError 是 URLError 的一个子类,用于处理特殊 HTTP 错误例如作为认证请求的时候,包含的属性 code 为 HTTP 的状态码, reason 为引发异常的原因,headers 为导致 HTTPError 的特定 HTTP 请求的 HTTP 响应头。

对不存在的网页抓取并处理异常:

1import urllib.request
2import urllib.error
3
4myURL1 = urllib.request.urlopen("https://www.runoob.com/")
5print(myURL1.getcode())   # 200
6
7try:
8    myURL2 = urllib.request.urlopen("https://www.runoob.com/no.html")
9except urllib.error.HTTPError as e:
10    if e.code == 404:
11        print(404)   # 404

encode()方法

描述

encode() 方法以 encoding 指定的编码格式编码字符串。errors 参数可以指定不同的错误处理方案。

语法

encode()方法语法:

1str.encode(encoding='UTF-8',errors='strict')

参数

  • encoding -- 要使用的编码,如"UTF-8"。
  • errors -- 设置不同错误的处理方案。默认为 'strict',意为编码错误引起一个 UnicodeError。 其他可能得值有 'ignore', 'replace', 'xmlcharrefreplace', 'backslashreplace' 以及通过 codecs.register_error() 注册的任何值。

返回值

该方法返回编码后的字符串。

decode()方法

描述

decode() 方法以 encoding 指定的编码格式解码字符串。默认编码为字符串编码。

语法

decode()方法语法:

1str.decode(encoding='UTF-8',errors='strict')

参数

  • encoding -- 要使用的编码,如"UTF-8"。
  • errors -- 设置不同错误的处理方案。默认为 'strict',意为编码错误引起一个 UnicodeError。 其他可能得值有 'ignore', 'replace', 'xmlcharrefreplace', 'backslashreplace' 以及通过 codecs.register_error() 注册的任何值。

返回值

该方法返回解码后的字符串。

post 请求案例百度翻译

  • Post 请求的参数必须编码,先通过urlencode转换为二进制形式,在通过encode转换为utf-8
  • 响应回来的数据是 json 需要进行反序列(loads)
1import json
2import urllib.request as request
3import urllib.parse as parse
4
5url = 'https://fanyi.baidu.com/sug'
6
7headers = {
8    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36"
9}
10
11data = {
12    'kw': 'spider'
13}
14
15# post 请求参数必须进行编码
16# urlencode 是讲对象转化为query路径参数的形式(kw=spider),如果用post请则必须通过encode('utf-8')在将其转化为二进制形式
17data = parse.urlencode(data).encode('utf-8')
18
19# 请求对象定制
20UrlALl = request.Request(url, data, headers=headers)
21
22# 发送请求
23response = request.urlopen(UrlALl)
24
25# 请求响应数据
26context = response.read().decode('utf8')
27
28obj = json.loads(context)
29
30print(obj)

有的加密接口会携带 cookie 或者其他令牌,这个不是固定的每个接口安全方式不一样,所有需要去分析,一般 cookie 是最常见的,在 headers 中添加

1headers = {
2    'Cookie': 'BAIDUID=A78C83243EC370D64EB9127421CDCD80:FG=1; BAIDUID_BFESS=A78C83243EC370D64EB9127421CDCD80:FG=1; BDUSS=duU0hBbzJhflBMQVZRMzB1Q0xRcHVKendKdnhRVjhiZkN1RzRwd0duQmc1eHRqSVFBQUFBJCQAAAAAAAAAAAEAAACWCc5fZ3bXytS0aG91c2UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBa9GJgWvRiNV; BDUSS_BFESS=duU0hBbzJhflBMQVZRMzB1Q0xRcHVKendKdnhRVjhiZkN1RzRwd0duQmc1eHRqSVFBQUFBJCQAAAAAAAAAAAEAAACWCc5fZ3bXytS0aG91c2UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBa9GJgWvRiNV; BIDUPSID=A78C83243EC370D64EB9127421CDCD80; PSTM=1660276134; ZFY=lTybp1mqT34VXA1zk3GnQ7ZEuvOwOkTsrZ5peYD5HLk:C; APPGUIDE_10_0_2=1; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1660527759; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1660527759; ab_sr=1.0.1_Y2RiYmNlYzA0MTQ1ZjA4Y2UzYWVjMDRmZWQxZjIwOTAyMGY3MDdmOThhYjIyZDk3ZTg2ZWE0OGE2YmIxYTBkNjIxYWI2ZGY3NjMzYmZiMTUwYjZkYTVkMWFhMzgzZWNlZjk4ZjYzYjRlODI1OTE5NjNhNDk1YTNmYzA2YTZjZDc1OGM2M2ZiMDkyM2JhMWU2MDExNWQwMWNmZWMyNTA3ZWViNmQzZjlmNGFjZWUwOGNmYmFkZDhhNDQxYjFlNTZi'
3}

handler 代理

1xxxxx
2
3request = request.Request(url, data, headers)
4
5proxies = {
6 'http':xxxxx
7}
8
9# hander build_opener open
10handler = urllib.request.build_.ProxyHandler(proxies = proxies)
11
12openr = urllib.request.build_opener(handler)
13
14response = openr.open(request)
15
16xxxxx