Python3的urllib库基本使用

一、简介

  • 介绍
    urllib是python自带的一个包,里面有很多处理url的模块。
 主要模块:
     urllib.request: 请求模块
     urllib.error: 异常处理模块
     urllib.parse: url解析模块
  • 官方文档
  https://docs.python.org/3/library/urllib.html
  • Python2和Python3
 Python2: urllib, urllib2
 Python3: urllib

Python 3.x中把urllib库和urilib2库合并成了urllib库。

二、主要的模块

urllib.request模块

  • 先来一个简单的例子
# 获取并打印百度的页面 GET请求
import urllib.request

response = urllib.request.urlopen('http://www.baidu.com')
print(response.read().decode('utf-8'))
  • urllib.request模块

urllib.requeset.urlopen(url,data,timeout):
  - 只传入url是get请求, 传入url和data是post请求
  - tiomeout:超时时间
  - 返回值: response对象

response对象:
  - read(): 获取字节类型的响应内容
  - geturl(): 获取请求的那个url
  - getheaders(): 获得响应头信息
  - getcode(): 获取状态码
  - readline(): 读取一行
  - readlines(): 返回一个列表,列表中是每一行内容

urllib.request.urlretrieve(url, path): 读取url内容,直接保存到本地
  - 可以根据url获取图片 
  - 根据url下载视频
  - 根据url下载网页
  - 从Python2模块urllib(而不是urllib2)移植,在将来的某个时候可能会被弃用
  • response实例
# 获取百度首页
# 查看对象中的一些属性
import urllib.request

url = 'http://www.baidu.com'
res_obj = urllib.request.urlopen(url)
print(res_obj.read())  # 可以获取二进制数据print(res_obj.readline())  # 按行读取print(res_obj.readlines())  # 获取多行 装入列表
print(res_obj.getcode())  # 服务器响应的状态码
print(res_obj.geturl())  # 响应的来源
print(res_obj.getheaders())  # 获取响应头

  • urllib.request.urlretrieve实例
# urlretrieve 根据地址获取资源
import urllib.request

# 获取图片
img_url = 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1540200586434&di=751ff5eb97f7388184dac2447ddeb170&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fimgad%2Fpic%2Fitem%2Ffc1f4134970a304e4aeda8dcdbc8a786c8175ccc.jpg'
# 传入 url路径 和 本地的路径(将来获取数据后保存到哪里)
urllib.request.urlretrieve(img_url,'./pengyou.jpg')

# 文本
text_url = 'http://www.baidu.com'
urllib.request.urlretrieve(text_url,'baidu.html')

# 视频
video_url = 'http://mvvideo11.meitudata.com/5bcc4b72dc93c4767.mp4?k=366fd214b835823cf8c2def8c6357e1c&t=5bd167d0'
urllib.request.urlretrieve(video_url,'xiaojiejie.mp4')

urllib.parse模块

  • quote() 编码
按照RFC规定 URL中不能出现 空格 中文,只允许一部分 ASCII字符(数字字母和部分符号),其他的字符(如汉字)是不符合 URL 标准的。所以,URL中使用其它字符就需要先进行编码。
  • unquote() 解码
其功能和quote相反, 对编码的内容进行解码。
  • urlencode()
对字典进行编码,把key-value这样的键值对转换成我们想要的格式,返回的是a=1&b=2这样的字符串
  • quote和unquote实例
import urllib.parse

# https://baike.baidu.com/item/%E5%B0%8F%E5%A5%B6%E7%8B%97/3266312?fr=aladdin
# url编码
# RFC规定 url中不能出现 空格 中文

# http://image.baidu.com/search/index?tn=baiduimage&ps=1&ct=201326592&lm=-1&cl=2&nc=1&ie=utf-8&word=%E7%8B%97

# 对url中的中文进行编码
# quote把中文转成url编码
code = urllib.parse.quote('小奶狗')
print(code)

# 对url编码的内容 进行 解码
word = urllib.parse.unquote('%E5%B0%8F%E5%A5%B6%E7%8B%97')
print(word)

  • urlencode实例
import urllib.parse

url = 'http://image.baidu.com/search/index?'
# http://image.baidu.com/search/index?tn=baiduimage&word=%E5%A5%B3%E6%9C%8B%E5%8F%8B

wd = '男朋友'
data = {
    'tn': 'baiduimage',
    'word': wd
}

# urlencode传入请求的数据对象 返回url编码后的字符串
query_string = urllib.parse.urlencode(data)
# print(query_string)
print(url + query_string)

三、请求头配置

  • 配置请求头
# 谷歌浏览器
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'
}

一般具有反爬虫的网站都会对请求头进行检查, 如果不携带请求头
服务器就会返回一个4xx的客户端相关的错误(甚至有的网站开发人员检查到爬虫后故意抛出5xx的服务器错误)。

  • 携带请求头
import urllib.request

url = 'http://www.baidu.com/'

# 把爬虫伪装成 pc端的浏览器
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'
}

# 创建请求对象
# 使用Request 传入 目标地址 请求参数 还有就是 字典形式的headers信息
request_obj = urllib.request.Request(url, headers=headers)

# urlopen的参数可以是简单的字符串 也可以是一个request请求对象
# 如果传入的是request请求对象则可以进行更高级的设置(比如设置headers)
response_obj = urllib.request.urlopen(request_obj)
print(response_obj.read())

  • POST请求
# ajax的post请求

import urllib.request
import urllib.parse

# 要请求的接口(手机端百度翻译的api接口,PC端的有验证 )
url = 'https://fanyi.baidu.com/sug'

"""
PC端百度翻译api接口需要的参数,sign是一个动态生成的值。每一次需要翻译的时候sign的值都会不一样
data = {
    'from': 'en',
    'to': 'zh',
    'query': 'wolf',
    'transtype': 'realtime',
    'simple_means_flag': '3',
    'sign': '275695.55262',
    'token': '67e2544c4cead16b8f4a9ac1c88e99d9',
}
"""
form_data = {
    'kw': '你好'
}
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'
}

# 如果没有请求头 headers 会被反爬
# 注意 传入的表单数据 需要是二进制数据, 所以我们需要对它进行编码
form_data_str = urllib.parse.urlencode(form_data)
# print(form_data_str)
# 把字符串变成二进制
bytes_data = form_data_str.encode()
# print(bytes_data)

request_obj = urllib.request.Request(url, data=bytes_data, headers=headers)
response_obj = urllib.request.urlopen(request_obj)
# 二进制变字符串 decode 解码
# 要把Unicode符号 中的中文显示出来 需要使用 unicode_escape进行解码
print(response_obj.read().decode('unicode_escape'))

四、URLError和HTTPError

Python中写爬虫程序时,可以使用urllib.error来接收urllib.request产生的异常。urllib.error有两个方法,URLError和HTTPError。

URLError是OSError的一个子类,HTTPError是URLError的一个子类,服务器上HTTP的响应会返回一个状态码,根据这个HTTP状态码,我们可以知道我们的访问是否成功。

  • URLError
from urllib import request
from urllib import error


    #一个不存在的连接
    url = "https://www.baidu.com/"
    req = request.Request(url)
    try:
        response = request.urlopen(req)
        html = response.read().decode('utf-8')
        print(html)
    except error.URLError as e:
        print(e.reason)

  • HTTPError
from urllib import request
from urllib import error

    #一个不存在的连接
    url = "https://www.baidu123321.com"
    req = request.Request(url)
    try:
        responese = request.urlopen(req)
    except error.HTTPError as e:
        print(e.code)

  • 一起使用
from urllib import request
from urllib import error

    url = "https://www.baidu123321.com"
    req = request.Request(url)
    try:
        response = request.urlopen(req)
        print("It's OK!")               # 正常
    except error.HTTPError as error:    # HTTP错误
        print('HTTPError')
        print('ErrorCode: %s' % error.code)
    except error.URLError as error:     # URL错误
        print(error.reason)

# 输入正确url时,以www.baidu.com为例
 It's OK!

# 输入一个不存在的域名时  URL错误
 [Errno 11001] getaddrinfo failed

# 输入一个正常的域名,但是不存在的资源时  HTTP错误
HTTPError
ErrorCode: 404

用HTTPError和URLError一起捕获异常,那么需要将HTTPError放在URLError的前面,因为HTTPError是URLError的一个子类。如果URLError放在前面,出现HTTP异常会先响应URLError,这样HTTPError就捕获不到错误信息了。

你可能感兴趣的:(Python3的urllib库基本使用)