之前用 Python 写的一个爬虫,现在用 Emacs 打开,提示找不到 urllib.urlopen
这个函数。调试了半天,就是提示找不到这个函数,但是这个爬虫却能正确执行。于是我打开Dash查看其 API,发现 API 中有这个函数,但是却不是使用 urllib.urlopen
来调用。而是变成了 urllib.request.urlopen
,仔细一看当前查看的是 Python3 的版本,看来是 Python 版本的锅。
urllib 简单介绍
urllib 是 Python3 中的标准网络请求库,使用 urllib 来获取网页的内容非常方便。在 Python2.x 版本中有 urllib 和 urllib2,但是到了 Python3 中 urllib 和 urllib2 被合并成了 urllib,所以之前在 Python2 中的写法就不能再出现在 Python3 中了。Python3 是趋势,所以折腾吧,少年。
先来看一下urllib 文档,从文档中可以看出 urllib 中主要有 request、error、parse、robotparser 四个模块,还是比较简单的,我们只介绍 request 其它的就不做介绍。
简单使用
1
2
3
4
|
from urllib import request
res = request.urlopen('http://www.baidu.com')
print(res.read().decode('utf-8'))
|
使用 urlopen
可以非常方便的以 GET
方式请求网页。运行代码就能看到百度首页的代码了。
添加请求参数
既然用 urlopen
可以非常方便的请求网页,如果要携带一些参数怎么办?
使用 GET
方式添加请求参数只需要在 url 后面拼接就可以,但是不要忘记对参数进行编码。
在 Python2 中 GET
参数使用的是 urllib.urlencode
,到了 Python3 这个函数被放到了 urllib 的 parse 中。
1
2
3
4
5
6
7
8
|
from urllib import request
from urllib import parse
q = {
'wd':'python'
}
url = 'http://www.baidu.com/s?'+parse.urlencode(q)
res = request.urlopen(url)
print(res.read().decode('utf-8'))
|
提交数据
常用的 http 请求方式除了 GET
外还有 POST
。 POST
通常用来提交数据给服务器。urllib 也提供了非常方便的方式来提交数据。
1
2
3
4
5
6
7
8
9
10
|
import urilib.parse
import urllib.request
url = "http://127.0.0.1:8080"
form = {
'username':'jake'
}
data = bytes(parse.urlencode(form), encoding='utf8')
res = request.urlopen(url, data=data)
print(res.read().decode('utf-8'))
|
进阶
urlopen
除了可以直接添加 url 外,还可以使用 Request
来定制请求。
Request 的使用
1
2
3
4
|
import urllib.request
req = request.Request('http://www.baidu.com')
res = request.urlopen(req)
print(res.read().decode('utf-8'))
|
上面的例子和使用 urlopen 是一样的效果。不同地方在于 request 可以进行定制。比如:请求头。
添加请求头
1
2
3
4
5
6
7
|
from urllib import request
headers={'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36'}
req = request.Request('http://www.baidu.com',headers = headers)
res = request.urlopen(req)
print(res.read().decode('utf-8'))
|
下面这种方式也是可以的
1
2
3
4
5
6
7
|
from urllib import request
req = request.Request('http://www.baidu.com')
req.add_header('User-Agent','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36')
res = request.urlopen(req)
print(res.read().decode('utf-8'))
|
Cookie
有些操作需要验证,如果每次使用都要验证,那就太麻烦了。所以我们需要把 cookie 保存下来,不要每次都去验证。当然把 cookie 放在头部也是可以的。
1
2
3
4
5
6
7
8
9
10
11
|
from urllib import request
import http.cookiejar
cookie = http.cookiejar.CookieJar()
handler = request.HTTPCookieProcessor(cookie)
opener = request.build_opener(handler)
res = opener.open('http://www.baidu.com')
print(res.read().decode('utf-8'))
for item in cookie:
print(item.name,':',item.value)
|
下载文件
有时候碰到一些资源想保存到本地,可以使用`urlretrieve`来把对应的资源下载到本地,也是很方便的。
1
2
3
|
from urllib import request
request.urlretrieve('http://www.baidu.com/img/bd_logo1.png','logo.png')
|
urlretrieve
第一个是资源的 url
,第二个是保存在本地的路径和文件名,如果没有填写第二个参数则保存为临时文件。
设置代理
临时代理
在一些特殊的情况下你想访问某个网站,但是你访问不到,另外一台主机可以。所以这台主机可以作为一台代理电脑,由它去访问我们访问不到的网站。通常爬虫被封了,就需要用到代理。
1
2
3
4
5
6
7
8
9
|
from urllib.request import ProxyHandler,build_opener
handler = ProxyHandler({
'http':'填上代理地址'
})
opener = build_opener(handler)
res = opener.open('http://www.baidu.com')
print(res.read())
|
代码还是很少的,只要用代理创建一个 opener
,然后使用 opener
就可以访问到网站了。
除了使用 ProxyHandler 之外还有 HTTPHandler 等,可以根据自己的需要选择需要的使用。
全局代理
1
2
3
4
5
6
7
8
9
10
11
|
from urllib.request import ProxyHandler,build_opener,Request
import urllib
handler = ProxyHandler({
'http':'代理地址'
})
opener = build_opener(handler)
urllib.request.install_opener(opener)
res = urllib.request.urlopen("http://www.baidu.com")
print(res.read())
|
全局代理使用 `urllib.request.install_opener(opener)` 把代理注册到全局,这样就能让所有的请求都通过代理。
如果请求每次都要使用代理,那么使用全局代理会省事不少,不必每次都创建代理。