一,獲取URL的內(nèi)容需要用到標準庫urllib包,其中的request模塊。
import urllib.request url = 'http://www.baidu.com' response = urllib.request.urlopen(url) string = response.read() html = string.decode( 'utf-8' ) print (html) |
urllib.request.
urlopen
(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
urlopen()方法返回一個<class 'http.client.HTTPResponse'>,即標準庫http包里的對象,該包是一個底層包,由request模塊調(diào)用。
read()方法返回一個<class 'bytes'>,字節(jié)對象是計算機認的,人看不懂。需要轉(zhuǎn)成人看得懂的字符串。
字節(jié)對象轉(zhuǎn)成str對象用str.decode()方法
二,將獲取的str對象內(nèi)容保存到HTML文件,需用到程序內(nèi)置的方法open()
f = open ( 'lc.html' , 'w' ) f.write(html) f.close() |
open()方法返回一個<class '_io.TextIOWrapper'>
write()方法是向文件對象寫入str內(nèi)容
最后要關閉文件對象
三,注:若上面的url換成http://www.baidu.com,則出現(xiàn)錯誤:
UnicodeEncodeError: 'gbk' codec can't encode character '\xbb' in position 29531: illegal multibyte sequence
原因分析:上面生成的lc.html用記事本打開,顯示文件編碼為ANSI,即gb2312編碼。
(不同的國家和地區(qū)制定了不同的標準,由此產(chǎn)生了 GB2312, BIG5, JIS 等各自的編碼標準。這些使用 2 個字節(jié)來代表一個字符的各種漢字延伸編碼方式,稱為 ANSI 編碼。在簡體中文系統(tǒng)下,ANSI 編碼代表 GB2312 編碼,在日文操作系統(tǒng)下,ANSI 編碼代表 JIS 編碼。)
如何以utf-8編碼來存儲lc.html文件呢?
1 | f = open ( 'lc.html' , 'w' ,encoding = 'utf-8' ) |
四,注: 若上面的URL換成https://www.foxizy.com/v-5zoc-235f23.html,則出現(xiàn)錯誤:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8b in position 1: invalid start byte
原因分析:服務器傳過來的內(nèi)容是壓縮格式(gzip),瀏覽器能夠自動解壓縮,而程序不能。
下面來看下http應答包的header部分:
>>> response.getheaders()
[('Server', 'nginx'), ('Date', 'Sun, 23 Jun 2019 00:25:46 GMT'), ('Content-Type', 'text/html; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Connection', 'close'), ('Cache-Control', 'public, max-age=252000'), ('Expires', 'Mon, 24 Jun 2019 07:14:39 GMT'), ('Last-Modified', 'Fri, 21 Jun 2019 09:14:39 GMT'), ('Content-Encoding', 'gzip'), ('N-Cache', 'HIT')]
從紅色部分可以看出,服務器返回的內(nèi)容經(jīng)過了gzip壓縮,所以需要解壓縮。
如何解決該問題:
1 2 | import zlib string = zlib.decompress(string,zlib.MAX_WBITS | 16 ) |
五,注:若urlopen()方法只傳入一個url地址參數(shù),則該HTTP請求的方法為GET請求。
如何進行POST請求呢?
1 2 3 4 | from urllib import request,parse<br>url = 'http://httpbin.org/post' <br>d = { 'name' : '張三' } da = parse.urlencode(d) data = bytes(da,encoding = 'utf-8' ) response = request.urlopen(url,data = data)<br> print (response.read().decode( 'utf-8' )) |
用了第二個參數(shù)data,就相當于post請求,但是data參數(shù)要求是字節(jié)(bytes)類型。
六,注:當我們想傳遞request headers的時候,urlopen就無法支持了,這里需要一個新的方法。
urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
from urllib import request,parse url = 'http://httpbin.org/post' headers = { 'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3100.0 Safari/537.36' , 'Host' : 'httpbin.org' } dict = { 'name' : 'zhangsan' } data = bytes(parse.urlencode( dict ),encoding = 'utf-8' ) req = request.Request(url = url,data = data,headers = headers,method = 'post' ) response = request.urlopen(req) print (response.read().decode( 'utf-8' )) |