$ ls ~yifei/notes/

Python urllib 模块

Posted on:

Last modified:

YN:网络访问的时候一定要记得设置一个合理的超时

在 Python 2 中,有两个 urllib:urllib 和 urllib2,urllib 基本只使用 urllib.urlencode(), urllib.quote 函数,其他功能都被对应的 urllib2 中的函数替代了。

Python3 把这两个模块进行了合并并拆分成了子模块,只使用 urllib 就好了。

实际上,在生产环境中,一般会用第三方的 http 库发起请求。不过有些 url 处理的函数还是经常用。

发送 http 请求

直接使用 urlopen

from urllib.request import urlopen

rsp = urlopen(url, data=None, [timeout, ] *, context) -> http.client.HTTPResponse

用于发送 GET 或者 POST 请求,如果有 data,则发送的是 POST 请求。返回一个 file-like 的 http.client.HTTPResponse 对象,这个对象也可以作为一个 context manager。

rsp.info()   # 返回 headers
rsp.gerurl()  # 返回 url,常用于判定是否被重定向
rsp.getcode()
rsp.read()/readlines()  # 返回文件内容
>>> from urllib.request import urlopen
>>> with urlopen("http://www.python.org/") as f:
...     print(f.read(300))
...
b"<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n\n\n<html
xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n\n<head>\n
<meta http-equiv="content-type" content="text/html; charset=utf-8" />\n
<title>Python Programming "

使用 Request 对象

如果需要更改默认的 header 等数据或者使用 PUT、DELETE 等方法,urlopen 还可以接受一个 Request 对象,可以在 Request 对象中更改。

Request 对象的定义:

from urllib.request import Request

class Request(url, data=None, headers={}, origin_req_host=None, unverifiable=Falsemethod=None)

一个 request 可以指定 method,url,可以使用 req.add_header 添加 header。

可以使用 add_header 方法再添加额外的 header,但是实际上是 set_header,并不能添加重复的, 不要被名字迷惑了。

使用 Opener

build_opener 返回一个打开器 OpenerDirector,用于设定发出请求要经过的一些处理,可以设定 代理,处理 cookie 等。OpenerDirector 有一个属性 addheaders,把他设定为一个包含 tuple 的 list,这样使用 opener 发送的每一个请求都会添加上这个 header。

from urllib.request import build_opener, HTTPCookieProcessor
from urllib.parse import urlencode
from cookielib import CookieJar

cj = CookieJar()

opener = build_opener(HTTPCookieProcessor(cj))
# input-type values from the html form
formdata = { "username" : username, "password": password, "form-id" : "1234" }
data_encoded = urlencode(formdata)
opener.addheaders = [("User-agent", "Mozilla/5.0")]
opener.open("http://www.example.com/")

response = opener.open("https://page.com/login.php", data_encoded)

异常

  • URLError, URLError 是 IOError 的子类
  • HTTPError, HTTPError.code

urllib.parse

尽量使用 urlsplit,不要使用 urlparse

urlsplit return a five element tuple by scheme://netloc/path?query#fragment

Attribute    Index    Value    Value if not present
scheme    0    URL scheme specifier    scheme parameter
netloc    1    Network location part    empty string
path    2    Hierarchical path    empty string
query    3    Query component    empty string
fragment    4    Fragment identifier    empty string
username         User name    None
password         Password    None
hostname         Host name (lower case)    None
port         Port number as integer, if present    None

Note, the netloc contains domain and port

>>> urlsplit("www.cwi.nl/%7Eguido/Python.html")
SplitResult(scheme="", netloc="", path="www.cwi.nl/%7Eguido/Python.html", query="", fragment="")
# notice the netloc will be wrong if "//" is missing
>>> urlsplit("//www.cwi.nl/%7Eguido/Python.html")
SplitResult(scheme="", netloc="www.cwi.nl", path="/%7Eguido/Python.html", query="", fragment="")

urlunsplit joins the parse result。

# parse a query string to { key: [values] } pair, note without '?'
parse_qs(qs, keep_blank_values=False, encoding="utf-8")
parse_qsl  # return a list of k,v tuple
quote/quote_plus
unquote
urlencode

参考

  1. http://stackoverflow.com/questions/3334809/python-urllib2-how-to-send-cookie-with-urlopen-request

© 2016-2022 Yifei Kong. Powered by ynotes

All contents are under the CC-BY-NC-SA license, if not otherwise specified.

Opinions expressed here are solely my own and do not express the views or opinions of my employer.