Python3 urllib

urllib.request 发 GET/POST 请求、设置请求头、解析 URL 与异常处理。

Intermediate
Key Points标准库自带 urllib,无需装包;日常项目更推荐 requests,但理解 urllib 能看清底层。

urllib.request

urllib.request.urlopen(url) opens a URL and returns a response object readable like a file. read() gives bytes that must be decoded using the charset from the headers.

Python
import urllib.request
import urllib.parse

req = urllib.request.Request('https://example.com')
print(req.get_method())
print(req.full_url)

print(urllib.parse.quote('中文 空格'))
print(urllib.parse.urlencode({'q': 'python', 'n': 2}))
Output
GET
https://example.com
%E4%B8%AD%E6%96%87%20%E7%A9%BA%E6%A0%BC
q=python&n=2

GET 请求

GET puts parameters in the query string and suits reads. Building it with urlencode percent-encodes automatically, so spaces and non-ASCII do not break.

Python
import urllib.parse

base = 'https://httpbin.org/get'
query = urllib.parse.urlencode({'q': 'python', 'page': 2})
url = base + '?' + query

print(url)
parts = urllib.parse.urlparse(url)
print(parts.netloc)
print(urllib.parse.parse_qs(parts.query))
Output
https://httpbin.org/get?q=python&page=2
httpbin.org
{'q': ['python'], 'page': ['2']}

POST 请求

POST sends data in the body, which must be encoded to bytes before passing as data=. Forms use application/x-www-form-urlencoded; JSON uses application/json.

Python
import urllib.parse
import json

form = urllib.parse.urlencode({'user': 'tom', 'pwd': 'x'}).encode()
print(form)

payload = json.dumps({'user': 'tom'}).encode()
print(payload)

print(len(form) > 0, len(payload) > 0)
Output
b'user=tom&pwd=x'
b'{"user": "tom"}'
True True

添加请求头

Many sites reject requests without a User-Agent. Build a Request(url, headers={...}, method=...) and hand it to urlopen.

Python
import urllib.request

req = urllib.request.Request(
    'https://example.com',
    headers={'User-Agent': 'BackendWiki/1.0', 'Accept': 'text/html'},
    method='GET',
)

print(req.get_header('User-agent'))
print(req.get_header('Accept'))
print(req.get_method())
Output
BackendWiki/1.0
text/html
GET

异常处理

Two exceptions matter: URLError (DNS failure, connection refused) and HTTPError (4xx/5xx responses). The latter subclasses the former, so catch it first.

Python
import urllib.error

print(issubclass(urllib.error.HTTPError, urllib.error.URLError))

try:
    raise urllib.error.HTTPError('https://x', 404, 'Not Found', {}, None)
except urllib.error.HTTPError as e:
    print("code:", e.code, "reason:", e.reason)
except urllib.error.URLError as e:
    print("url error:", e.reason)
Output
True
code: 404 reason: Not Found

Friends & Partners