urllib 是 Python3 中自带的 HTTP 请求库,无需复杂的安装过程便可正常使用,十分适合爬虫入门html
urllib 中包含四个模块,分别是python
如下咱们将会分别讲解 urllib 中各模块的使用方法,可是因为篇幅问题,本文只会涉及模块中比较经常使用的内容json
详细内容能够参考官方文档:https://docs.python.org/3.7/library/urllib.html浏览器
在开始讲解前,先给你们提供一个用于测试的网站,http://www.httpbin.org/cookie
这个网站能够在页面上返回所发送 请求 的相关信息,十分适合练习使用网络
好了,下面正式开始!session
request 模块是 urllib 中最重要的一个模块,通常用于 发送请求和接收响应app
urllib.request.urlopen()
urlopen 方法无疑是 request 模块中最经常使用的方法之一,常见的参数说明以下:dom
url
:必填,字符串,指定目标网站的 URLsocket
data
:指定表单数据
该参数默认为 None,此时 urllib 使用 GET 方法 发送请求
当给参数赋值后,urllib 使用 POST 方法 发送请求,并在该参数中携带表单信息(bytes 类型)
timeout
:可选参数,用来指定等待时间,若超过指定时间还没得到响应,则抛出一个异常
该方法始终返回一个 HTTPResponse 对象,HTTPResponse 对象常见的属性和方法以下:
geturl()
:返回 URLgetcode()
:返回状态码getheaders()
:返回所有响应头信息getheader(header)
:返回指定响应头信息read()
:返回响应体(bytes 类型),一般须要使用 decode('utf-8')
将其转化为 str 类型例子1:发送 GET 请求
>>> import urllib.request >>> url = 'http://www.httpbin.org/get' >>> response = urllib.request.urlopen(url) >>> type(response) # <class 'http.client.HTTPResponse'> >>> response.geturl() # 'http://www.httpbin.org/get' >>> response.getcode() # 200 >>> response.getheaders() # [('Connection', 'close'), ('Server', 'gunicorn/19.9.0'), ('Date', 'Sat, 11 Aug 2018 01:39:14 GMT'), ('Content-Type', 'application/json'), ('Content-Length', '243'), ('Access-Control-Allow-Origin', '*'), ('Access-Control-Allow-Credentials', 'true'), ('Via', '1.1 vegur')] >>> response.getheader('Connection') # 'close' >>> print(response.read().decode('utf-8')) # { # "args": {}, # "headers": { # "Accept-Encoding": "identity", # "Host": "www.httpbin.org", # "User-Agent": "Python-urllib/3.7" # }, # "origin": "183.6.159.80, 183.6.159.80", # "url": "https://www.httpbin.org/get" # }
例子2:发送 POST 请求
urllib.parse.urlencode()
:进行 URL 编码,其实是将 dict 类型数据转化成 str 类型数据
encode('utf-8')
:将 str 类型数据转化成 bytes 类型数据
>>> import urllib.request >>> import urllib.parse >>> url = 'http://www.httpbin.org/post' >>> params = { 'from':'AUTO', 'to':'AUTO' } >>> data = urllib.parse.urlencode(params).encode('utf-8') >>> response = urllib.request.urlopen(url=url,data=data) >>> html = response.read().decode('utf-8') >>> print(html) # { # "args": {}, # "data": "", # "files": {}, # "form": { # 这是咱们设置的表单数据 # "from": "AUTO", # "to": "AUTO" # }, # "headers": { # "Accept-Encoding": "identity", # "Connection": "close", # "Content-Length": "17", # "Content-Type": "application/x-www-form-urlencoded", # "Host": "www.httpbin.org", # "User-Agent": "Python-urllib/3.6" # }, # "json": null, # "origin": "116.16.107.180", # "url": "http://www.httpbin.org/post" # }
实际上,咱们还能够给 urllib.request.open()
方法传入一个 Request 对象做为参数
为何还须要使用 Request 对象呢?由于在上面的参数中咱们没法指定 请求头部,而它对于爬虫而言又十分重要
不少网站可能会首先检查请求头部中的 USER-AGENT
字段来判断该请求是否由网络爬虫程序发起
可是经过修改请求头部中的 USER_AGENT
字段,咱们能够将爬虫程序假装成浏览器,轻松绕过这一层检查
这里提供一个查找经常使用的 USER-AGENT 的网站:
urllib.request.Request()
参数说明以下:
url
:指定目标网站的 URLdata
:发送 POST 请求时提交的表单数据,默认为 Noneheaders
:发送请求时附加的请求头部,默认为 {}origin_req_host
:请求方的 host 名称或者 IP 地址,默认为 Noneunverifiable
:请求方的请求没法验证,默认为 Falsemethod
:指定请求方法,默认为 None>>> import urllib.request >>> url = 'http://www.httpbin.org/headers' >>> headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36' } >>> req = urllib.request.Request(url, headers=headers, method='GET') >>> response = urllib.request.urlopen(req) >>> html = response.read().decode('utf-8') >>> print(html) # { # "headers": { # "Accept-Encoding": "identity", # "Connection": "close", # "Host": "www.httpbin.org", # "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36" 这是咱们设置的 User-Agent # } # }
什么是 Cookie?
Cookie 是指某些网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据
① 获取 Cookie
>>> import urllib.request >>> import http.cookiejar >>> cookie = http.cookiejar.CookieJar() >>> cookie_handler = urllib.request.HTTPCookieProcessor(cookie) >>> opener = urllib.request.build_opener(cookie_handler) >>> response = opener.open('http://www.baidu.com') >>> for item in cookie: print(item.name + '=' + item.value) # BAIDUID=486AED46E7F22C0A7A16D9FE6E627846:FG=1 # BDRCVFR[RbWYmTxDkZm]=mk3SLVN4HKm # BIDUPSID=486AED46E7F22C0A7A16D9FE6E627846 # H_PS_PSSID=1464_21106_26920 # PSTM=1533990197 # BDSVRTM=0 # BD_HOME=0 # delPer=0
② 使用 Cookie
>>> import urllib.request >>> import http.cookiejar >>> # 将 Cookie 保存到文件 >>> cookie = http.cookiejar.MozillaCookieJar('cookie.txt') >>> cookie_handler = urllib.request.HTTPCookieProcessor(cookie) >>> opener = urllib.request.build_opener(cookie_handler) >>> response = opener.open('http://www.baidu.com') >>> cookie.save(ignore_discard=True,ignore_expires=True) >>> # 从文件读取 Cookie 并添加到请求中 >>> cookie = http.cookiejar.MozillaCookieJar() >>> cookie = cookie.load('cookie.txt',ignore_discard=True,ignore_expires=True) >>> cookie_handler = urllib.request.HTTPCookieProcessor(cookie) >>> opener = urllib.request.build_opener(cookie_handler) >>> response = opener.open('http://www.baidu.com') >>> # 此时已经获得带有 Cookie 请求返回的响应
对于某些网站,若是同一个 IP 短期内发送大量请求,则可能会将该 IP 断定为爬虫,进而对该 IP 进行封禁
因此咱们有必要使用随机的 IP 地址来绕开这一层检查,这里提供几个查找免费的 IP 地址的网站:
注意,免费的代理 IP 基本上十分不稳定,并且还可能随时更新,因此最好本身写一个爬虫去维护
>>> import urllib.request >>> import random >>> ip_list = [ {'http':'61.135.217.7:80'}, {'http':'182.88.161.204:8123'} ] >>> proxy_handler = urllib.request.ProxyHandler(random.choice(ip_list)) >>> opener = urllib.request.build_opener(proxy_handler) >>> response = opener.open('http://www.httpbin.org/ip') >>> print(response.read().decode('utf-8')) # { # "origin": "61.135.217.7" # }
parse 模块通常能够用于处理 URL
当你在 URL 中使用中文时,你会发现程序会出现莫名其妙的错误
>>> import urllib.request >>> url = 'https://www.baidu.com/s?wd=爬虫' >>> response = urllib.request.urlopen(url) # UnicodeEncodeError: 'ascii' codec can't encode characters in position 10-11: ordinal not in range(128)
这时,quote 方法就能够派上用场了,它使用转义字符替换特殊字符,从而将上面的 URL 处理成合法的 URL
>>> import urllib.parse >>> url = 'https://www.baidu.com/s?wd=' + urllib.parse.quote('爬虫') >>> url # 'https://www.baidu.com/s?wd=%E7%88%AC%E8%99%AB'
urlencode 方法在上面的文章中曾经用到过,不知道你们还有没有印象,这里咱们再从新回顾一遍
简单来讲,urlencode 方法就是将 dict 类型数据转化为符合 URL 标准的 str 类型数据,请看演示:
>>> import urllib.parse >>> params = { 'from':'AUTO', 'to':'AUTO' } >>> data = urllib.parse.urlencode(params) >>> data # 'from=AUTO&to=AUTO'
urlparse 方法用于解析 URL,返回一个 ParseResult 对象
该对象能够认为是一个六元组,对应 URL 的通常结构:scheme://netloc/path;parameters?query#fragment
>>> import urllib.parse >>> url = 'http://www.example.com:80/python.html?page=1&kw=urllib' >>> url_after = urllib.parse.urlparse(url) >>> url_after # ParseResult(scheme='http', netloc='www.example.com:80', path='/python.html', params='', query='page=1', fragment='urllib') >>> url_after.port # 80
error 模块通常用于进行异常处理,其中包含两个重要的类:URLError
和 HTTPError
注意,HTTPError 是 URLError 的子类,因此捕获异常时通常要先处理 HTTPError,经常使用的格式以下:
>>> import urllib.request >>> import urllib.error >>> import socket >>> try: response = urllib.request.urlopen('http://www.httpbin.org/get', timeout=0.1) except urllib.error.HTTPError as e: print("Error Code: ", e.code) print("Error Reason: ", e.reason) except urllib.error.URLError as e: if isinstance(e.reason, socket.timeout): print('Time out') else: print('Request Successfully') # Time out
【参考资料】
【爬虫系列相关文章】