官方文档地址:https://docs.python.org/3/library/urllib.html
Urllib 是 python 内置的 HTTP 请求库包括以下模块 urllib.request 请求模块 urllib.error 异常处理模块 urllib.parse url 解析模块 urllib.robotparser robots.txt 解析模块
关于 urllib.request.urlopen 参数的介绍:urllib.request.urlopen(url, data=None, [timeout,]*, cafile=None, capath=None, cadefault=False, context=None)
url 参数的使用
先写一个简单的例子:
- import urllib.request
- response = urllib.request.urlopen('http://www.baidu.com')
- print(response.read().decode('utf-8'))
urlopen 一般常用的有三个参数,它的参数如下:urllib.requeset.urlopen(url,data,timeout)response.read() 可以获取到网页的内容,如果没有 read(),将返回如下内容
data 参数的使用
上述的例子是通过请求百度的 get 请求获得百度,下面使用 urllib 的 post 请求这里通过 http://httpbin.org/post 网站演示(该网站可以作为练习使用 urllib 的一个站点使用,可以模拟各种请求操作)。
- import urllib.parse
- import urllib.request
- data = bytes(urllib.parse.urlencode({'word':'hello'}), encoding='utf8')
- print(data)
- response = urllib.request.urlopen('http://httpbin.org/post', data=data)
- print(response.read())
这里就用到 urllib.parse,通过 bytes(urllib.parse.urlencode()) 可以将 post 数据进行转换放到 urllib.request.urlopen 的 data 参数中。这样就完成了一次 post 请求。所以如果我们添加 data 参数的时候就是以 post 请求方式请求,如果没有 data 参数就是 get 请求方式
timeout 参数的使用在某些网络情况不好或者服务器端异常的情况会出现请求慢的情况,或者请求异常,所以这个时候我们需要给请求设置一个超时时间,而不是让程序一直在等待结果。例子如下:
- import urllib.request
- response = urllib.request.urlopen('http://httpbin.org/get', timeout=1)
- print(response.read())
运行之后我们看到可以正常的返回结果,接着我们将 timeout 时间设置为 0.1 运行程序会提示如下错误
所以我们需要对异常进行抓取,代码更改为
- import socket
- import urllib.request
- import urllib.error
- try:
- response = urllib.request.urlopen('http://httpbin.org/get', timeout=0.1)
- except urllib.error.URLError as e:
- if isinstance(e.reason, socket.timeout):
- print('TIME OUT')
响应类型、状态码、响应头
- import urllib.request
- response = urllib.request.urlopen('https://www.python.org')
- print(type(response))
可以看到结果为:
当然上述的 urlopen 只能用于一些简单的请求,因为它无法添加一些 header 信息,如果后面写爬虫我们可以知道,很多情况下我们是需要添加头部信息去访问目标站的,这个时候就用到了 urllib.request
设置 Headers 有很多网站为了防止程序爬虫爬网站造成网站瘫痪,会需要携带一些 headers 头部信息才能访问,最长见的有 user-agent 参数
写一个简单的例子:
- import urllib.request
- request = urllib.request.Request('https://python.org')
- response = urllib.request.urlopen(request)
- print(response.read().decode('utf-8'))
给请求添加头部信息,从而定制自己请求网站是时的头部信息
- fromurllibimport request, parse
- url ='http://httpbin.org/post'
- headers = {
- 'User-Agent':'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)',
- 'Host':'httpbin.org'
- }
- dict = {
- 'name':'zhaofan'
- }
- data = bytes(parse.urlencode(dict), encoding='utf8')
- req = request.Request(url=url, data=data, headers=headers, method='POST')
- response = request.urlopen(req)
- print(response.read().decode('utf-8'))
添加请求头的第二种方式
- fromurllibimport request, parse
- url ='http://httpbin.org/post'
- dict = {
- 'name':'Germey'
- }
- data = bytes(parse.urlencode(dict), encoding='utf8')
- req = request.Request(url=url, data=data, method='POST')
- req.add_header('User-Agent','Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)')
- response = request.urlopen(req)
- print(response.read().decode('utf-8'))
这种添加方式有个好处是自己可以定义一个请求头字典,然后循环进行添加
高级用法各种 handler
代理, ProxyHandler
通过 rulllib.request.ProxyHandler() 可以设置代理, 网站它会检测某一段时间某个 IP 的访问次数,如果访问次数过多,它会禁止你的访问, 所以这个时候需要通过设置代理来爬取数据
- import urllib.request
- proxy_handler = urllib.request.ProxyHandler({
- 'http':'http://127.0.0.1:9743',
- 'https':'https://127.0.0.1:9743'
- })
- opener = urllib.request.build_opener(proxy_handler)
- response = opener.open('http://httpbin.org/get')
- print(response.read())
cookie,HTTPCookiProcessor
cookie 中保存中我们常见的登录信息,有时候爬取网站需要携带 cookie 信息访问, 这里用到了 http.cookijar,用于获取 cookie 以及存储 cookie
- import http.cookiejar, urllib.request
- cookie = http.cookiejar.CookieJar()
- handler = urllib.request.HTTPCookieProcessor(cookie)
- opener = urllib.request.build_opener(handler)
- response = opener.open('http://www.baidu.com')
- foritemin cookie:
- print(item.name+"="+item.value)
同时 cookie 可以写入到文件中保存,有两种方式 http.cookiejar.MozillaCookieJar 和 http.cookiejar.LWPCookieJar(),当然你自己用哪种方式都可以
具体代码例子如下:http.cookiejar.MozillaCookieJar() 方式
- import http.cookiejar, urllib.request
- filename ="cookie.txt"
- cookie = http.cookiejar.MozillaCookieJar(filename)
- handler = urllib.request.HTTPCookieProcessor(cookie)
- opener = urllib.request.build_opener(handler)
- response = opener.open('http://www.baidu.com')
- cookie.save(ignore_discard=True, ignore_expires=True)
http.cookiejar.LWPCookieJar() 方式
- import http.cookiejar, urllib.request
- filename ='cookie.txt'
- cookie = http.cookiejar.LWPCookieJar(filename)
- handler = urllib.request.HTTPCookieProcessor(cookie)
- opener = urllib.request.build_opener(handler)
- response = opener.open('http://www.baidu.com')
- cookie.save(ignore_discard=True, ignore_expires=True)
同样的如果想要通过获取文件中的 cookie 获取的话可以通过 load 方式,当然用哪种方式写入的,就用哪种方式读取。
- import http.cookiejar, urllib.request
- cookie = http.cookiejar.LWPCookieJar()
- cookie.load('cookie.txt', ignore_discard=True, ignore_expires=True)
- handler = urllib.request.HTTPCookieProcessor(cookie)
- opener = urllib.request.build_opener(handler)
- response = opener.open('http://www.baidu.com')
- print(response.read().decode('utf-8'))
在很多时候我们通过程序访问页面的时候,有的页面可能会出现错误,类似 404,500 等错误这个时候就需要我们捕捉异常,下面先写一个简单的例子
- fromurllibimport request,error
- try:
- response = request.urlopen("http://pythonsite.com/1111.html")
- except error.URLError as e:
- print(e.reason)
上述代码访问的是一个不存在的页面,通过捕捉异常,我们可以打印异常错误
这里我们需要知道的是在 urllb 异常这里有两个个异常错误:URLError,HTTPError,HTTPError 是 URLError 的子类
URLError 里只有一个属性:reason, 即抓异常的时候只能打印错误信息,类似上面的例子
HTTPError 里有三个属性:code,reason,headers,即抓异常的时候可以获得 code,reson,headers 三个信息,例子如下:
- fromurllibimport request,error
- try:
- response = request.urlopen("http://pythonsite.com/1111.html")
- except error.HTTPError as e:
- print(e.reason)
- print(e.code)
- print(e.headers)
- except error.URLError as e:
- print(e.reason)
- else:
- print("reqeust successfully")
同时,e.reason 其实也可以在做深入的判断,例子如下:
- import socket
- fromurllibimport error,request
- try:
- response = request.urlopen("http://www.pythonsite.com/",timeout=0.001)
- except error.URLError as e:
- print(type(e.reason))
- if isinstance(e.reason,socket.timeout):
- print("time out")
urlparseThe URL parsing functions focus on splitting a URL string into its components, or on combining URL components into a URL string.
urllib.parse.urlparse(urlstring, scheme='', allow_fragments=True)
功能一:
- fromurllib.parseimport urlparse
- result = urlparse("http://www.baidu.com/index.html;user?id=5#comment")
- print(result)
结果为:
这里就是可以对你传入的 url 地址进行拆分同时我们是可以指定协议类型:result = urlparse("www.baidu.com/index.html;user?id=5#comment",scheme="https") 这样拆分的时候协议类型部分就会是你指定的部分,当然如果你的 url 里面已经带了协议,你再通过 scheme 指定的协议就不会生效
urlunpars
其实功能和 urlparse 的功能相反,它是用于拼接,例子如下:
- fromurllib.parseimport urlunparse
- data = ['http','www.baidu.com','index.html','user','a=123','commit']
- print(urlunparse(data))
结果如下
urljoin
这个的功能其实是做拼接的,例子如下:
- fromurllib.parseimport urljoin
- print(urljoin('http://www.baidu.com','FAQ.html'))
- print(urljoin('http://www.baidu.com','https://pythonsite.com/FAQ.html'))
- print(urljoin('http://www.baidu.com/about.html','https://pythonsite.com/FAQ.html'))
- print(urljoin('http://www.baidu.com/about.html','https://pythonsite.com/FAQ.html?question=2'))
- print(urljoin('http://www.baidu.com?wd=abc','https://pythonsite.com/index.php'))
- print(urljoin('http://www.baidu.com','?category=2#comment'))
- print(urljoin('www.baidu.com','?category=2#comment'))
- print(urljoin('www.baidu.com#comment','?category=2'))
结果为:
从拼接的结果我们可以看出,拼接的时候后面的优先级高于前面的 url
urlencode 这个方法可以将字典转换为 url 参数,例子如下
- fromurllib.parseimport urlencode
- params = {
- "name":"zhaofan",
- "age":23,
- }
- base_url ="http://www.baidu.com?"
- url = base_url+urlencode(base_url)
- print(url)
结果为:
来源: http://www.cnblogs.com/zhaof/p/6910871.html