環境
- Win7+Python2.7
- urllib+urllib2
[!] urllib模塊和urllib2模塊的區別
urllib2可以接受一個Request類的實例來設置URL請求的headers,urllib僅可以接受URL。
urllib提供urlencode方法用來GET查詢字符串的產生,而urllib2沒有。
工作流程
定位需要爬取的頁面,糗事百科首頁https://www.qiushibaike.com/
用urllib2的Request類構建一個request
url = "https://www.qiushibaike.com/"
request = urllib2.Request(url)
接下來用urllib2的urlopen方法來請求頁面,並獲取響應(即頁面內容)
response = urllib2.urlopen(request)
打印獲取到的內容
print response.read()
運行我們的腳本,結果報錯了:
Traceback (most recent call last):
File "00_get_a_page.py", line 19, in <module>
response = urllib2.urlopen(request)
File "D:\Python27\lib\urllib2.py", line 154, in urlopen
return opener.open(url, data, timeout)
File "D:\Python27\lib\urllib2.py", line 429, in open
response = self._open(req, data)
File "D:\Python27\lib\urllib2.py", line 447, in _open
'_open', req)
File "D:\Python27\lib\urllib2.py", line 407, in _call_chain
result = func(*args)
File "D:\Python27\lib\urllib2.py", line 1241, in https_open
context=self._context)
File "D:\Python27\lib\urllib2.py", line 1201, in do_open
r = h.getresponse(buffering=True)
File "D:\Python27\lib\httplib.py", line 1121, in getresponse
response.begin()
File "D:\Python27\lib\httplib.py", line 438, in begin
version, status, reason = self._read_status()
File "D:\Python27\lib\httplib.py", line 402, in _read_status
raise BadStatusLine(line)
httplib.BadStatusLine: ''
這是因爲糗事百科針對爬蟲的一些反爬優化,必須是瀏覽器才能訪問頁面。
不過沒關係,瀏覽器的信息是通過headers
實現的,我們可以用urllib2設置瀏覽器信息頭,把我們的程序僞裝成瀏覽器。
設置頭部驗證信息
user_agent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36 LBBROWSER"
headers = {"User-Agent":user_agent}
可以看到我們設置了User-Agent
這個字段,並將其封裝爲一個字典headers
,後面我們會用到這個headers
。
user_agent
的內容是Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36 LBBROWSER
,這個是我是用的獵豹瀏覽器的頭部信息,通過F12開發者工具可以查看到。
重新構造請求,並打印獲取到的響應頁面的內容
request = urllib2.Request(url,headers=headers)
可以發現我們在構造request時除了url參數,還將剛纔封裝好的帶有瀏覽器信息的headers
傳給了urllib2.Request
的headers參數。
[!] 必須指定headers=headers
,否則會默認將headers傳遞給urllib2.Request的第二個參數,但是第二個參數並非headers,如下:
>>> help("urllib2.Request")
Help on class Request in urllib2:
urllib2.Request = class Request
| Methods defined here:
| __getattr__(self, attr)
| __init__(self, url, data=None, headers={}, origin_req_host=None, unverifiable=False)
同樣的再重新請求頁面,獲取響應並打印出來
response = urllib2.urlopen(request)
print response.read()
獲取成功!但是我們的漢字並沒有顯示出來。
這是因爲我們獲取到的response.read()的編碼方式是UTF-8的字節流數據,而我們python2.7的默認編解碼方式爲ASCII,從而導致了亂碼。
我們打印時指定解碼方式爲UTF-8試試看。
print response.read().decode('utf-8')
成功!
至此我們獲取了完整的整個頁面信息。