# urllib 基本使用

# 简介

urllib 是 python 内置的一个网络库,我们可以直接导入该库,然后使用它去模拟浏览器向服务器发送请求以获取数据。

# 导入请求对象
import urllib.request
baseUrl = 'http://www.baidu.com'
# 通过 baseUrl 发送请求
respone = urllib.request.urlopen(url = baseUrl)
# 获取回的 respone 为一个对象,调用 read 方法逐字节读取响应数据
content = respone.read()
# respone.readline () 仅读取一行内容
# respone.readlines () 一行一行读取所有内容,返回一个字节流形式的数据的 list
# content 是字节流的形式存储的数据,所以要转换为 utf-8 字符串
result = content.decode('utf-8')
# 输出最终的 html 文档
print(result)

# 构造 http 请求头

有时候网站会要求识别请求的 UA 来反爬,或者需要爬取登录后才能查看的数据时要携带 cookie 。我们可以使用 urllib 库里带的函数去构造出 http 请求头来绕过。

image-20220605155834239

import urllib.request
baseUrl = 'https://asuhe.fun'
# 构造 http 请求头,携带 UA
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.63 Safari/537.36'
}
# 将构造好的请求头封装进 Request 对象
request = urllib.request.Request(url = baseUrl,headers = headers)
# 发送请求
respone = urllib.request.urlopen(request)

# handler 构造请求头

当我们需要使用 动态cookie 或者 ip代理 等高级功能时,上面构造的请求头已经无法满足。 handler 则可以实现这个功能。

# 在上面代码的基础上,使用 handler 对象即可
# 1. 创建 handler 对象
handler = urllib.request.HTTPHandler()
# 2. 构建 opener 对象
opener = urllib.request.build_opener(handler)
# 3. 调用 opener 对象的 open 方法请求,传入 request 对象
respone = opener.open(request)

# 使用代理

使用代理 ip 访问网站可以提高访问速度,突破网站访问的限制。

import urllib.request
baseUrl = 'http://www.baidu.com'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.63 Safari/537.36'
}
# 1. 创建 request 对象
request = urllib.request.Request(url=baseUrl,headers=headers)
# 2. 创建 ProxyHandler 对象
proxies = {
    # 设置代理 ip 和端口
    'http':'110.110.110.110:996'
}
proxyHandler = urllib.requers.ProxyHandler(proxies = proxies)
# 3. 创建 opener 对象
opener = urllib.request.build_opener(proxyHandler)
# 4. 使用 open 方法访问
respone = opener.open(request)

使用代理池

proxiesPool = [
    {'http':'110.110.110.110:996'},
    {'http':'111.110.110.110:996'},
    {'http':'112.110.110.110:996'}
]
import random
proxies = random.choice(proxiesPool)

# get 和 post 请求的编码处理

无论是 get 还是 post ,在发送前如果携带参数中有中文或者非 utf-8 字符,则都需要先编码,然后才能发送出去。

import urllib.request
import urllib.parse
# 处理单个参数
baseUrl1 = 'http://www.baidu.com/s?wd='
query = '明日'
# 编码单个参数
encoded = urllib.parse.quote(query) 
print(encoded) # %E6%98%8E%E6%97%A5
respone1 = urllib.request.urlopen(url = baseUrl1 + encoded)
# 处理多个参数
baseUrl2 = 'http://www.baidu.com/s?'
querys = {
    'wd':'明日',
    'sex':'男'
}
data = urllib.parse.urlencode(querys)
respone = urllib.request.urlopen(url = baseUrl2 + data)

# 发送 post 请求

import urllib.request
import urllib.parse
baseUrl = 'https://fanyi.baidu.com/v2transapi?from=en&to=zh'
data = {
    'from': 'en'
    'to': 'zh'
    'query': 'spider'
    'transtype': 'realtime'
    'simple_means_flag': '3'
    'sign': '63766.268839'
    'token': '122223c8769458b6eb3613362ad8693e'
    'domain': 'common'
}
params = urllib.parse.urlencode(data)
# post 请求的参数必须编码为字节流的形式
params = params.encode('utf-8')
# urllib.request.Request 的 data 参数即为 post 请求携带的参数
request = urllib.request.Request(url = baseUrl,data = params)
respone = urllib.request.urlopen(request)

# json 处理

有时候我们请求网页返回来的是 json 格式的数据,这时我们要使用 json 模块去解析数据

import json
jsonData = json.loads(data) # data 为响应的 json 数据

# 异常处理

若通过 urllib 发送请求产生异常,通常为两种:一种是 URLError ,另一种是 HTTPErrorURLError 当请求的主机地址错误时会发生, HTTPError 例如当无法连接到主机时,请求携带的参数错误时,都会产生该错误。 HTTPErrorURLError 的子类。

import urllib.error
try:
    # code
except urllib.error.HTTPError:
    # something
except urllib.error.URLError:
    # something