網絡爬蟲,也叫網絡蜘蛛(Web Spider),若是把互聯網比喻成一個蜘蛛網,Spider就是一隻在網上爬來爬去的蜘蛛。網絡爬蟲就是根據網頁的地址來尋找網頁的,也就是URL。舉一個簡單的例子,咱們在瀏覽器的地址欄中輸入的字符串就是URL,例如:https://www.baidu.com/html
URL就是贊成資源定位符(Uniform Resource Locator),它的通常格式以下(帶方括號[]的爲可選項):python
protocol :// hostname[:port] / path / [;parameters][?query]#fragment
URL的格式由三部分組成:es6
(1)protocol:第一部分就是協議,例如百度使用的就是https協議;json
(2)hostname[:port]:第二部分就是主機名(還有端口號爲可選參數),通常網站默認的端口號爲80,例如百度的主機名就是www.baidu.com,這個就是服務器的地址;api
(3)path:第三部分就是主機資源的具體地址,如目錄和文件名等。瀏覽器
網絡爬蟲就是根據這個URL來獲取網頁信息的。服務器
爬蟲基本流程:markdown
urllib提供了一系列用於操做URL的功能。
Python3中將python2.7的urllib和urllib2兩個包合併成了一個urllib庫,其主要包括一下模塊:cookie
urllib.request 請求模塊網絡
urllib.error 異常處理模塊
urllib.parse url解析模塊
urllib.robotparser robots.txt解析模塊
咱們使用urllib.request.urlopen()這個接口函數就能夠很輕鬆的打開一個網站,也就是發送一個GET請求到指定的頁面,而後返回HTTP的響應,urlopen參數以下:
urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
urllib使用使用request.urlopen()打開和讀取URLs信息,返回的對象response如同一個文本對象,咱們能夠調用read(),進行讀取,一樣也可使用geturl()方法、info()方法、getcode()方法。
例如,對csdn首頁https://www.csdn.net進行抓取,並返回響應:
from urllib import request with request.urlopen('https://www.csdn.net/') as f: data = f.read() print('Status:', f.status, f.reason) for k, v in f.getheaders(): print('%s: %s' % (k, v)) print('Data:', data.decode('utf-8')) # 能夠看到HTTP響應的頭和JSON數據: ''' Status: 200 OK Server: openresty Date: Mon, 15 Jul 2019 07:31:40 GMT Content-Type: text/html; charset=UTF-8 Transfer-Encoding: chunked Connection: close Vary: Accept-Encoding Set-Cookie: uuid_tt_dd=10_35252089750-1563175899898-449903; Expires=Thu, 01 Jan 2025 00:00:00 GMT; Path=/; Domain=.csdn.net; Set-Cookie: dc_session_id=10_1563175899898.455037; Expires=Thu, 01 Jan 2025 00:00:00 GMT; Path=/; Domain=.csdn.net; Vary: Accept-Encoding Strict-Transport-Security: max-age=31536000 Data: <!DOCTYPE html>...</script></div></html> '''
若是咱們要想模擬瀏覽器發送GET請求,就須要使用Request對象,經過往Request對象添加http請求頭User-Agent,咱們就能夠把請求假裝成瀏覽器。例如,模擬手機端iphone6去請求csdn首頁:
from urllib import request req = request.Request('https://www.csdn.net') req.add_header('User-Agent', 'Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25') with request.urlopen(req) as f: print('Status:', f.status, f.reason) for k, v in f.getheaders(): print('%s: %s' % (k, v)) print('Data:', f.read().decode('utf-8')) #返回適合iPhone的移動版網頁: ''' <meta charset="utf-8"> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=Edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> '''
User Agent
有一些網站不喜歡被爬蟲程序訪問,因此會檢測鏈接對象,若是是爬蟲程序,也就是非人點擊訪問,它就會不讓你繼續訪問,因此爲了要讓程序能夠正常運行,須要隱藏本身的爬蟲程序的身份。此時,咱們就能夠經過設置User Agent的來達到隱藏身份的目的,User Agent的中文名爲用戶代理,簡稱UA。
User Agent存放於Headers中,服務器就是經過查看Headers中的User Agent來判斷是誰在訪問。在Python中,若是不設置User Agent,程序將使用默認的參數,那麼這個User Agent就會有Python的字樣,若是服務器檢查User Agent,那麼沒有設置User Agent的Python程序將沒法正常訪問網站。
Python容許咱們修改這個User Agent來模擬瀏覽器訪問,它的強大毋庸置疑。
經常使用的瀏覽器請求頭User-Agent彙總:
user_agent = [ "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50", "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50", "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0", "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; InfoPath.3; rv:11.0) like Gecko", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", "Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11", "Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; The World)", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SE 2.X MetaSr 1.0; SE 2.X MetaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Avant Browser)", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)", "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5", "Mozilla/5.0 (iPod; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5", "Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5", "Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", "MQQBrowser/26 Mozilla/5.0 (Linux; U; Android 2.3.7; zh-cn; MB200 Build/GRJ22; CyanogenMod-7) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", "Opera/9.80 (Android 2.3.4; Linux; Opera Mobi/build-1107180945; U; en-GB) Presto/2.8.149 Version/11.10", "Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13", "Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; en) AppleWebKit/534.1+ (KHTML, like Gecko) Version/6.0.0.337 Mobile Safari/534.1+", "Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.0; U; en-US) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/233.70 Safari/534.6 TouchPad/1.0", "Mozilla/5.0 (SymbianOS/9.4; Series60/5.0 NokiaN97-1/20.0.019; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebKit/525 (KHTML, like Gecko) BrowserNG/7.1.18124", "Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; HTC; Titan)", "UCWEB7.0.2.37/28/999", "NOKIA5700/ UCWEB7.0.2.37/28/999", "Openwave/ UCWEB7.0.2.37/28/999", "Mozilla/4.0 (compatible; MSIE 6.0; ) Opera/UCWEB7.0.2.37/28/999", # iPhone 6: "Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25", ]
f.read().decode(‘utf-8’) 這就是瀏覽器接收到的信息,只不過咱們在使用瀏覽器的時候,瀏覽器已經將這些信息轉化成了界面信息供咱們瀏覽。固然這些代碼咱們也能夠從瀏覽器中點擊(F12或者開發者選項中)查看到。固然這個前提是咱們已經知道了這個網頁是使用utf-8編碼的,怎麼查看網頁的編碼方式呢?須要人爲操做,且很是簡單的方法是使用使用瀏覽器開發者選項,只須要找到head標籤開始位置的chareset,就知道網頁是採用何種編碼的了。以下:
咱們可使用data參數,向服務器發送數據。根據HTTP規範,GET用於信息獲取,POST是向服務器提交數據的一種請求,
若是沒有設置urlopen()函數的data參數,HTTP請求採用GET方式,也就是咱們從服務器獲取信息,若是咱們設置data參數,HTTP請求採用POST方式,也就是咱們向服務器傳遞數據。
data參數有本身的格式,它是一個基於application/x-www.form-urlencoded的格式,具體格式咱們不用瞭解, 由於咱們可使用urllib.parse.urlencode()函數將字符串自動轉換成上面所說的格式。
舉例子說明:向有道翻譯發送data,獲得翻譯結果。
具體詳情見:https://blog.csdn.net/weixin_42251851/article/details/80489403
urllib提供的功能就是利用程序去執行各類HTTP請求。若是要模擬瀏覽器完成特定功能,須要把請求假裝成瀏覽器。假裝的方法是先監控瀏覽器發出的請求,再根據瀏覽器的請求頭來假裝,User-Agent頭就是用來標識瀏覽器的。
Python內置的urllib模塊,用於訪問網絡資源。可是,它用起來比較麻煩,並且,缺乏不少實用的高級功能。
更好的方案是使用requests。它是一個Python第三方庫,處理URL資源特別方便。
使用requests要經過GET訪問一個頁面,只須要幾行代碼:
import requests r = requests.get('https://www.csdn.net/') print(r.status_code) print(r.text)
對於帶參數的URL,傳入一個dict做爲params參數:
r = requests.get('https://www.douban.com/search', params={'q': 'python', 'cat': '1001'}) print(r.url) # 實際請求的URL ''' 'https://www.douban.com/search?q=python&cat=1001' '''
requests自動檢測編碼,可使用encoding屬性查看:
print(r.encoding) ''' 'utf-8' '''
不管響應是文本仍是二進制內容,咱們均可以用content屬性得到bytes對象:
print(r.content) ''' b'<!DOCTYPE html>\n<html>\n<head>\n<meta http-equiv="Content-Type" content="text/html; charset=utf-8">\n...' '''
requests的方便之處還在於,對於特定類型的響應,例如JSON,能夠直接獲取:
r = requests.get('https://query.yahooapis.com/v1/public/yql? r.json()
須要傳入HTTP Header時,咱們傳入一個dict做爲headers參數:
r = requests.get('https://www.douban.com/', headers={'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit'})
要發送POST請求,只須要把get()方法變成post(),而後傳入data參數做爲POST請求的數據:
r = requests.post('https://accounts.douban.com/login', data={'form_email': 'abc@example.com', 'form_password': '123456'})
requests默認使用application/x-www-form-urlencoded對POST數據編碼。若是要傳遞JSON數據,能夠直接傳入json參數:
params = {'key': 'value'} r = requests.post(url, json=params) # 內部自動序列化爲JSON
相似的,上傳文件須要更復雜的編碼格式,可是requests把它簡化成files參數:
upload_files = {'file': open('report.xls', 'rb')} r = requests.post(url, files=upload_files)
在讀取文件時,注意務必使用’rb’即二進制模式讀取,這樣獲取的bytes長度纔是文件的長度。
把post()方法替換爲put(),delete()等,就能夠以PUT或DELETE方式請求資源。
除了能輕鬆獲取響應內容外,requests對獲取HTTP響應的其餘信息也很是簡單。例如,獲取響應頭:
r.headers
requests對Cookie作了特殊處理,使得咱們沒必要解析Cookie就能夠輕鬆獲取指定的Cookie:
print(r.cookies['ts']) ''' 'example_cookie_12345' '''
要在請求中傳入Cookie,只需準備一個dict傳入cookies參數:
cs = {'token': '12345', 'status': 'working'} r = requests.get(url, cookies=cs)
最後,要指定超時,傳入以秒爲單位的timeout參數:
r = requests.get(url, timeout=2.5) # 2.5秒後超時
更多詳細介紹,可參考:http://www.javashuo.com/article/p-awbuoqmy-nt.html
https://www.liaoxuefeng.com/wiki/1016959663602400/1183249464292448