Python3.x爬蟲教程:爬網頁、爬圖片、本身主動登陸

林炳文Evankaka原創做品。

轉載請註明出處http://blog.csdn.net/evankaka
html

摘要:本文將使用Python3.4爬網頁、爬圖片、本身主動登陸。並對HTTP協議作了一個簡單的介紹。在進行爬蟲以前,先簡單來進行一個HTTP協議的解說。這樣如下再來進行爬蟲就是理解更加清楚。java

1、HTTP協議

       HTTP是Hyper Text Transfer Protocol(超文本傳輸協議)的縮寫。python

它的發展是萬維網協會(World Wide Web Consortium)和Internet工做小組IETF(Internet Engineering Task Force)合做的結果,(他們)終於公佈了一系列的RFC。RFC 1945定義了HTTP/1.0版本號。當中最著名的就是RFC 2616。RFC 2616定義了今天廣泛使用的一個版本號——HTTP 1.1。web


       HTTP協議(HyperText Transfer Protocol。超文本傳輸協議)是用於從WWWserver傳輸超文本到本地瀏覽器的傳送協議。它可以使瀏覽器更加高效,使網絡傳輸下降。編程

它不只保證計算機正確高速地傳輸超文本文檔。還肯定傳輸文檔中的哪一部分。以及哪部份內容首先顯示(如文本先於圖形)等。
瀏覽器

 HTTP的請求響應模型cookie

HTTP協議永遠都是client發起請求,server回送響應。見下圖:網絡

  


這樣就限制了使用HTTP協議,沒法實現在client沒有發起請求的時候。server將消息推送給client。

HTTP協議是一個無狀態的協議。同一個client的此次請求和上次請求是沒有相應關係。併發

工做流程app

一次HTTP操做稱爲一個事務。其工做過程可分爲四步:

1)首先客戶機與server需要創建鏈接。僅僅要單擊某個超級連接,HTTP的工做開始。

2)創建鏈接後。客戶機發送一個請求給server。請求方式的格式爲:統一資源標識符(URL)、協議版本號號。後邊是MIME信息包括請求修飾符、客戶機信息和可能的內容。

3)server接到請求後,給予相應的響應信息,其格式爲一個狀態行,包括信息的協議版本號號、一個成功或錯誤的代碼,後邊是MIME信息包括server信息、實體信息和可能的內容。

4)client接收server所返回的信息經過瀏覽器顯示在用戶的顯示屏上,而後客戶機與server斷開鏈接。

假設在以上過程當中的某一步出現錯誤,那麼產生錯誤的信息將返回到client,有顯示屏輸出。

對於用戶來講。這些過程是由HTTP本身完畢的,用戶僅僅要用鼠標點擊,等待信息顯示就可以了

請求報頭
請求報頭贊成client向server端傳遞請求的附加信息以及client自身的信息。
常用的請求報頭
Accept
Accept請求報頭域用於指定client接受哪些類型的信息。eg:Accept:image/gif。代表client但願接受GIF圖象格式的資源。Accept:text/html,代表client但願接受html文本。
Accept-Charset
Accept-Charset請求報頭域用於指定client接受的字符集。eg:Accept-Charset:iso-8859-1,gb2312.假設在請求消息中沒有設置這個域,缺省是不論什麼字符集都可以接受。
Accept-Encoding
Accept-Encoding請求報頭域類似於Accept,但是它是用於指定可接受的內容編碼。eg:Accept-Encoding:gzip.deflate.假設請求消息中沒有設置這個域server假定client對各類內容編碼都可以接受。


Accept-Language
Accept-Language請求報頭域類似於Accept,但是它是用於指定一種天然語言。eg:Accept-Language:zh-cn.假設請求消息中沒有設置這個報頭域,server假定client對各類語言都可以接受。
Authorization
Authorization請求報頭域主要用於證實client有權查看某個資源。當瀏覽器訪問一個頁面時,假設收到server的響應代碼爲401(未受權),可以發送一個包括Authorization請求報頭域的請求,要求server對其進行驗證。


Host(發送請求時,該報頭域是必需的)
Host請求報頭域主要用於指定被請求資源的Internet主機和端口號。它一般從HTTP URL中提取出來的,eg:
咱們在瀏覽器中輸入:http://www.guet.edu.cn/index.html
瀏覽器發送的請求消息中,就會包括Host請求報頭域。例如如下:
Host:
www.guet.edu.cn
此處使用缺省端口號80,若指定了端口號,則變成:Host:www.guet.edu.cn:指定端口號
User-Agent
咱們上網登錄論壇的時候,每每會看到一些歡迎信息。當中列出了你的操做系統的名稱和版本號,你所使用的瀏覽器的名稱和版本號,這每每讓很是多人感到很是奇妙,實際上,server應用程序就是從User-Agent這個請求報頭域中獲取到這些信息。User-Agent請求報頭域贊成client將它的操做系統、瀏覽器和其餘屬性告訴server。只是。這個報頭域不必的。假設咱們本身編寫一個瀏覽器。不使用User-Agent請求報頭域。那麼server端就沒法得知咱們的信息了。


請求報頭舉例:
GET /form.html HTTP/1.1 (CRLF)
Accept:image/gif,image/x-xbitmap,image/jpeg,application/x-shockwave-flash,application/vnd.ms-excel,application/vnd.ms-powerpoint,application/msword,*/* (CRLF)
Accept-Language:zh-cn (CRLF)
Accept-Encoding:gzip,deflate (CRLF)
If-Modified-Since:Wed,05 Jan 2007 11:21:25 GMT (CRLF)
If-None-Match:W/"80b1a4c018f3c41:8317" (CRLF)
User-Agent:Mozilla/4.0(compatible;MSIE6.0;Windows NT 5.0) (CRLF)
Host:www.guet.edu.cn (CRLF)
Connection:Keep-Alive (CRLF)
(CRLF)

GET /form.html HTTP/1.1 (CRLF)Accept:image/gif,image/x-xbitmap,image/jpeg,application/x-shockwave-flash,application/vnd.ms-excel,application/vnd.ms-powerpoint,application/msword,*/* (CRLF)Accept-Language:zh-cn (CRLF)Accept-Encoding:gzip,deflate (CRLF)If-Modified-Since:Wed,05 Jan 2007 11:21:25 GMT (CRLF)If-None-Match:W/"80b1a4c018f3c41:8317" (CRLF)User-Agent:Mozilla/4.0(compatible;MSIE6.0;Windows NT 5.0) (CRLF)Host:www.guet.edu.cn (CRLF)Connection:Keep-Alive (CRLF)(CRLF)


響應報頭
響應報頭贊成server傳遞不能放在狀態行中的附加響應信息。以及關於server的信息和對Request-URI所標識的資源進行下一步訪問的信息。
常用的響應報頭
Location
Location響應報頭域用於重定向接受者到一個新的位置。Location響應報頭域常用在更換域名的時候。
Server
Server響應報頭域包括了server用來處理請求的軟件信息。

與User-Agent請求報頭域是相相應的。如下是
Server響應報頭域的一個樣例:
Server:Apache-Coyote/1.1
WWW-Authenticate
WWW-Authenticate響應報頭域必須被包括在401(未受權的)響應消息中,client收到401響應消息時候,併發送Authorization報頭域請求server對其進行驗證時,服務端響應報頭就包括該報頭域。
eg:WWW-Authenticate:Basic realm="Basic Auth Test!"  //可以看出server對請求資源採用的是基本驗證機制。

2、Python3.4爬蟲編程

一、第一個演示樣例,咱們要來進行簡單的爬蟲來爬別人的網頁

#python3.4 爬蟲教程
#一個簡單的演示樣例爬蟲
#林炳文Evankaka(博客:http://blog.csdn.net/evankaka/)
import urllib.request
url = "http://www.douban.com/"
webPage=urllib.request.urlopen(url)
data = webPage.read()
data = data.decode('UTF-8')
print(data)
print(type(webPage))
print(webPage.geturl())
print(webPage.info())
print(webPage.getcode())
這是爬回來的網頁輸出:

這中間究竟發生了什麼事呢?讓咱們打開Fiddler來看看吧:

左邊標紅的就表示咱們本次訪問成功,爲http 200

右邊上方這是python生成 的請求報頭。不清楚看如下:

很是easy的一個報頭。而後再來看看響應回來的html

這裏響應回來的就是咱們上面在python的idle中打印出來的網頁了!


二、假裝成瀏覽器來爬網頁

有些網頁,比方登陸的。假設你不是從瀏覽器發起的起求,這就不會給你響應,這時咱們就需要本身來寫報頭。而後再發給網頁的server,這時它就覺得你就是一個正常的瀏覽器。從而就可以爬了!

#python3.4 爬蟲教程
#一個簡單的演示樣例爬蟲
#林炳文Evankaka(博客:http://blog.csdn.net/evankaka/)
import urllib.request
weburl = "http://www.douban.com/"
webheader = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0'} 
req = urllib.request.Request(url=weburl, headers=webheader)  
webPage=urllib.request.urlopen(req)
data = webPage.read()
data = data.decode('UTF-8')
print(data)
print(type(webPage))
print(webPage.geturl())
print(webPage.info())
print(webPage.getcode())
來看看請求報頭,就是和咱們設置的一個樣。


返回的是同樣的:

再來一個複雜一點的請求報頭:

#python3.4 爬蟲教程
#一個簡單的演示樣例爬蟲
#林炳文Evankaka(博客:http://blog.csdn.net/evankaka/)
import urllib.request
weburl = "http://www.douban.com/"
webheader1 = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0'}
webheader2 = {
    'Connection': 'Keep-Alive',
    'Accept': 'text/html, application/xhtml+xml, */*',
    'Accept-Language': 'en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3',
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko',
    #'Accept-Encoding': 'gzip, deflate',
    'Host': 'www.douban.com',
    'DNT': '1'
    }
req = urllib.request.Request(url=weburl, headers=webheader2)  
webPage=urllib.request.urlopen(req)
data = webPage.read()
data = data.decode('UTF-8')
print(data)
print(type(webPage))
print(webPage.geturl())
print(webPage.info())
print(webPage.getcode())

看看生成 的結果:

返回仍是:

三、爬取站點上的圖片

前面咱們可以爬網頁了,下一步咱們就可以批量的本身主動下載該網頁上的各類數據了~,比方。這裏我要下載該網頁上的所有圖片

#python3.4 爬蟲教程
#爬取站點上的圖片
#林炳文Evankaka(博客:http://blog.csdn.net/evankaka/)
import urllib.request  
import socket  
import re  
import sys  
import os  
targetDir = r"D:\PythonWorkPlace\load"  #文件保存路徑
def destFile(path):  
    if not os.path.isdir(targetDir):  
        os.mkdir(targetDir)  
    pos = path.rindex('/')  
    t = os.path.join(targetDir, path[pos+1:])  
    return t  
if __name__ == "__main__":  #程序執行入口
    weburl = "http://www.douban.com/"
    webheaders = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0'} 
    req = urllib.request.Request(url=weburl, headers=webheaders)  #構造請求報頭
    webpage = urllib.request.urlopen(req)  #發送請求報頭
    contentBytes = webpage.read()  
    for link, t in set(re.findall(r'(http:[^\s]*?

(jpg|png|gif))', str(contentBytes))): #正則表達式查找所有的圖片 print(link) try: urllib.request.urlretrieve(link, destFile(link)) #下載圖片 except: print('失敗') #異常拋出

這是正在執行的過程:

打開電腦上相應的目錄,而後來看看圖片。這裏僅僅是一部分哦!!

。。

真實的網頁上的圖片

四、保存爬取回來的報文

def saveFile(data):
    save_path = 'D:\\temp.out'
    f_obj = open(save_path, 'wb') # wb 表示打開方式
    f_obj.write(data)
    f_obj.close()
 
# 這裏省略爬蟲代碼
# ...
 
# 爬到的數據放到 dat 變量裏
# 將 dat 變量保存到 D 盤下
saveFile(dat)

比方:

#python3.4 爬蟲教程
#一個簡單的演示樣例爬蟲
#林炳文Evankaka(博客:http://blog.csdn.net/evankaka/)
import urllib.request
def saveFile(data):
    save_path = 'D:\\temp.out'
    f_obj = open(save_path, 'wb') # wb 表示打開方式
    f_obj.write(data)
    f_obj.close()
weburl = "http://www.douban.com/"
webheader1 = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0'}
webheader2 = {
    'Connection': 'Keep-Alive',
    'Accept': 'text/html, application/xhtml+xml, */*',
    'Accept-Language': 'en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3',
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko',
    #'Accept-Encoding': 'gzip, deflate',
    'Host': 'www.douban.com',
    'DNT': '1'
    }
req = urllib.request.Request(url=weburl, headers=webheader2)  
webPage=urllib.request.urlopen(req)
data = webPage.read()
saveFile(data)# 將data變量保存到 D 盤下
data = data.decode('UTF-8')
print(data)
print(type(webPage))
print(webPage.geturl())
print(webPage.info())
print(webPage.getcode())


而後看看D盤:

用NotePad打開:


嗯嗯。

是對的。網頁已經被爬下來了。

3、Python3.x 本身主動登陸

通常狀況下咱們輸入郵箱和密碼後,登陸。

來看看。

這就是提交表單的內容

python3.4代碼編寫:

import gzip
import re
import http.cookiejar
import urllib.request
import urllib.parse
#解壓函數
def ungzip(data):
    try:        # 嘗試解壓
        print('正在解壓.....')
        data = gzip.decompress(data)
        print('解壓完畢!')
    except:
        print('未經壓縮, 無需解壓')
    return data
#獲取_xsrf 
def getXSRF(data):
    cer = re.compile('name=\"_xsrf\" value=\"(.*)\"', flags = 0)
    strlist = cer.findall(data)
    return strlist[0]
#構造文件頭
def getOpener(head):
    #設置一個cookie處理器,它負責從server下載cookie到本地。並且在發送請求時帶上本地的cookie
    cj = http.cookiejar.CookieJar()
    pro = urllib.request.HTTPCookieProcessor(cj)
    opener = urllib.request.build_opener(pro)
    header = []
    for key, value in head.items():
        elem = (key, value)
        header.append(elem)
    opener.addheaders = header
    return opener
#構造header,通常header至少要包括一下兩項。

這兩項是從抓到的包裏分析得出的。 header = { 'Connection': 'Keep-Alive', 'Accept': 'text/html, application/xhtml+xml, */*', 'Accept-Language': 'en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3', 'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko', 'Accept-Encoding': 'gzip, deflate', 'Host': 'www.zhihu.com', 'DNT': '1' } url = 'http://www.zhihu.com/' opener = getOpener(header) op = opener.open(url) data = op.read() data = ungzip(data) # 解壓 _xsrf = getXSRF(data.decode()) #post數據接收和處理的頁面(咱們要向這個頁面發送咱們構造的Post數據) url += 'login/email' id = '這裏寫本身的郵箱' password = '這裏寫本身的密碼' #構造Post數據,他也是從抓大的包裏分析得出的。 postDict = { '_xsrf':_xsrf, #特有數據。不一樣站點可能不一樣 'email': id, 'password': password, 'rememberme': 'y' } #需要給Post數據編碼 postData = urllib.parse.urlencode(postDict).encode() op = opener.open(url, postData) data = op.read() data = ungzip(data) print(data.decode())


來看看結果:

這時執行返回的

發送出去的請求頭

接收回來 的報頭

返回的數據是什麼意思呢:

很是easy, 咱們轉碼下:

相關文章
相關標籤/搜索