Python爬蟲心得
一、前言
學習了爬蟲之后,突然對crawler這個詞產生了濃厚的興趣,爬蟲,很形象,很生動,在python中,爬蟲的使用更加的快捷和方便,在這里將自己的一些心得予以記憶,加深印象!!!!!!
二、python爬蟲
要點一:
python版本的選取,這里選取的是3.*,我們知道每一個版本很多的庫和函數都做了相應的調整,如果不好好的掌握這一點,我們可能拿到別人的程序也無法使用。比如print函數,在3.*中是print(),具體的改動可以參考網址http://www.jb51.net/article/57956.htm來進行相關的學習。
要點二:
選擇一個好的編譯器,這點非常重要,這里選擇的是pycharm,功能強大,支持調試等各種手段。
要點三:
理解python3.*的一些庫函數,比如抓取網頁用的urllib.request,用於正則表達式的re等,以及時間庫函數time,隨機數庫函數random。
要點四:python的主函數
1 If __name__=’__main__’: 2 3 /*函數體*/
要點五:編碼轉換。
1 import re 2 from urllib.request import urlopen 3 def catchAllInfoFromNet( myUrl): 4 html = urlopen(myUrl).read().decode('utf-8','ignore') 5 #print(html) 6 #nameList = re.compile(r'<title>(.*?)</title>', re.DOTALL).findall(html) # 列表形式 7 #nameList = re.compile(r'href="(.*?)"', re.DOTALL).findall(html) # 列表形式 8 #nameList = re.compile(r'"name": "(.*?)"', re.DOTALL).findall(html) # 列表形式 9 nameList = re.compile(r'<p>(.*?)</p>', re.DOTALL).findall(html) # 列表形式 10 for i in range(0, len(nameList)): 11 print("第%d個名字為: %s"%(i,nameList[i]))
上面是一段源碼,我們看到需要將字節轉換成字符,這點非常重要。
要點六:對於如何下載網頁。
這里有兩種方法,一種如上面的代碼所示,使用from urllib.request import urlopen來直接使用urlopen來抓取。
第二種是使用urllib.request來獲得,代碼如下:
1 import urllib.request 2 import re 3 def catchAllInfoFromNet(url): 4 #模擬瀏覽器,打開url 5 headers = ('User-Agent','Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11') 6 opener = urllib.request.build_opener() 7 opener.addheaders = [headers] 8 data = opener.open(url).read().decode('utf-8','ignore') 9 nameList = re.compile(r'<p>(.*?)</p>', re.DOTALL).findall(data) # 列表形式 10 for i in range(0, len(nameList)): 11 print("第%d個名字為: %s" % (i, nameList[i]))
這種方式我們要偽裝成瀏覽器進行網頁抓取。
當然也可以:
1 import urllib.request 2 import re 3 def catchAllInfoFromNet(url): 4 data = urllib.request.urlopen(url).read().decode('UTF-8') 5 nameList = re.compile(r'<p>(.*?)</p>', re.DOTALL).findall(data) 6 for i in range(0, len(nameList)): 7 print("第%d個名字為: %s" % (i, nameList[i]))
要點六:正則表達式
可以參考http://blog.csdn.net/peace1213/article/details/48950593進行學習。

三、Python實現登錄爬蟲代碼
最近,對python的研究幾乎是到了上癮的地步,一個工具如果好到了一定的程度,就算沒有人去宣傳它,推廣它,這個工具也會成為大家心里最喜愛的工具的,用了python之后才感覺到以前的C/C++,C#和Java實在是不夠簡練,可能是術業有專攻吧,可是python的哲學色彩真的很濃厚,有很多值得我們去學習和借鑒的地方,正如工具的本質就是繼承大量固有的操作,只留一些接口,從而來方便大家的操作和使用,在這一點上,我深有同感,特別是對於網絡爬蟲來說,python可以說真的封裝到了一種瓶頸了,用其他語言需要幾百行實現的代碼,python只需要我們做幾十行的工作,這一點就深深值得我們去思考和借鑒。下面就寫一下這幾天我是用python爬蟲的體會。正如以前所言,爬蟲的幾個要點都已經說過了,可是正當我高興的那前人的代碼去爬取網頁數據的時候,一個問題才出現了,需要登錄,現在很多網站都有這個功能,不登錄就不能使用爬蟲來抓取自己需要的數據了,這不得不說是魔高一尺,道高一丈。這對於網站來說當然是一種進步了,可是對於我們爬蟲族來說實在是一個既刺激又煩惱的消息,刺激在於我們就是要和這些網站斗智斗勇,煩惱在於面對與一次次的失敗我們是否能平淡視之,不斷地積累經驗教訓,不斷地完善自己,這一點至關重要。下面就開始我的心得體會了。
難點一:登錄需要的參數都有些什么?
首先一定要有的就是賬號和密碼了,除此之外或許還有驗證碼,說到了驗證碼,我們就有犯難了,可能是網站看到我們很容易的破解了他們的登錄阻擋策略,而又想出的新一代安全手段吧。因為驗證碼多種多樣,用代碼識別也是可以的,不過要付出很多的代價,而我們自己看的話,也可以,這樣對我我們初學者不失為一種好的方法。
難點二:如果只是簡單的賬號密碼性的網站,我們怎么模擬賬號和密碼?
這一點我們不得不學習一下瀏覽器是怎么實現這樣的功能的,其實很簡單,一切都在應用層協議里,比如HTTP,HTTPS協議,在這些協議里封裝了一些特殊的字段,用來識別用戶的一些信息,比如所用的瀏覽器,發送的賬號密碼等等,於是我們就可以根據這些信息來進行偽造從而迷惑服務器了,這點我們再上一次已經講過,我們的程序也就是這樣做的,那在這里,這些賬號密碼肯定也是放在這些字段中的,我們要做的是將這些數據提交到那些包里面,因此,在這里我們就需要用到cookie了,cookie英文意思是小點心,它確實是我們的“小點心”呀,它的里面存儲的東西是非常重要的,如果我們在瀏覽器上保存了賬號,密碼等信息,那么就會被存到瀏覽器對應的cookie里,放在本地主機,比如說firefox瀏覽器的cookie就在選項——》隱私——》自定義設置——》顯示cookie里,如下圖所示,不同的瀏覽器可能有所不同,cookie存儲的內容也很簡單易懂,就是一個映射,Map(key,value),一個鍵值對的映射,比如我們的賬戶,Account:Account Value,這就是一種映射,因此,我們要搞定用戶名和密碼,就要知道在實際傳輸中,當前網站所有的這些信息,一般情況下賬號名是不加密的,而密碼一定是加密傳輸的,不過這並不影響我們去識別它,那么問題來了,我們怎么去識別賬戶名和密碼的字段呢?至於真正的賬戶名和密碼,我們可以自己注冊一個,這都無關緊要,可是我們怎么知道我們的鍵(key)呢?!

這些往往在python登錄的教程里沒講,而我們確實真正要用到的,因此這里我一定着重講一下,不然這對初學者來說是極其痛苦的,很難理清思路,很困惑,樓主都被困了整整一個上午才找到解決方案,不過也學到了一些知識,在這里給大家分享:
首先,讓我們思考,我們可不可以在瀏覽器中,用F12來調用網頁自帶的開發工具來查找呢?!在網上也有這樣的例子,比如:在firefox中有一個插件叫做firebug,我們可以安裝它之后來捕捉:

下面我們都用人人網為例來進行實驗,無它,沒有驗證碼也!!!
首先我們安裝firebug,重啟瀏覽器,之后我們在人人網上按F12進入開發者模式,如下圖所示:

我們點擊cookie可以看到如下的字段,這里放大:

很自然地驚訝這些東西都是什么,是cookie呀,我們還能看到這些是來自那個網頁的cookie,不過我們怎么從這些字段中知道那些是我們要找的賬號和密碼呢?很難,並且我可以告訴大家的是這些都不是,網上的很多文章真的是夠混帳的,弄出來浪費我們的時間?!其實可能有其他的用吧,可是卻是對於我們的工作幫助不大。比如說下面的一個cookie顯示的內容是我的賬號,我當時還高興了很久,覺得總算找到了一個字段了,可是仔細看看,In_uact這個是什么鬼?!我們也不得而知,只能說你是不是在逗我,當然了這些背后肯定有具體的含義,可在這里與我們無關吶。

當然我們辛辛苦苦下載的firebug也不是一無是處嘛,只是我們可以看到一些瀏覽器的參數,包的header,等信息。在調試器的“網絡”中,我們可以看到。這些信息或許對我們以后的學習有用,反正先記着吧。這些就是網上能夠看到的內容了,下面我介紹一下,我的方法,當時我也認為沒辦法了,這些東西一點都不直觀明了,並且感覺總有些不對的感覺,幸好我在網上看到了抓包分析的方法,恰好,我也在想可不可以用抓包的方法來檢測呢?!沿着這個思路,我又開始了進一步的探索!!!

網絡抓包有很多種方法,比如wireshark、fiddler等,這里我用慣了前者,就用用后者吧,后來發現網上對它的評論還不錯,尤其是對https協議來說,fiddler確實是一個比較不錯的選擇,比較小,短小精悍。Fiddle的本意是“小提琴”或者“胡扯,無聊,欺詐,欺騙”,不能理解為什么小提琴會和欺詐扯上關系,我想fiddler肯定是借鑒了欺詐的意義,因為抓包本來就是一種竊取信息的行為,甚至還可以偽造成新的包,因此名字起的還是很形象。下載並安裝fiddler,之后如圖所示:

然后,我們首先打開fiddler,注意一定要先打開,然后切換瀏覽器到人人網頁面,用自己的賬號密碼登錄網站,此時fiddler就開始抓取我們和服務器進行交互的信息了,如下圖所示:

點擊登錄,就進入下面界面:

此時可以看到fiddler中的信息:

其中result為200的說明是抓取成功的,我們一個個的點擊查看,觀看右邊Inspect上面的webforms來觀看,直到點擊到第五個url為“/ajaxLogin/。。。”的這一個包的時候,我們發現右邊的結果如下圖所示:(賬號名是email,沒加密,密碼是加密的,為password)


終於我們找到了這個東西,我們需要的cookie,那大家有可能會說有可能是瀏覽器迷惑我們,故意寫的這些字段呢,其實是把別的偽裝成了這樣呢,確實有可能,比如淘寶就有兩個密碼TPL_password和TPL_password_2,經過我的觀察,后者才是真正的密碼,前者為空,當然具體問題具體分析,我們一個一個試探,總能出結果的,這就是黑客的基本素質了,不氣餒,一直積累經驗,不斷嘗試。同理,我們還可以在這個包中讀出cookie,看來,我們剛開始認為的字段的名稱在cookie里根本就沒有呀,這一點到底是為什么,我相信在以后的學習中會漸漸理解的。

找到了重要的兩個信息,我們是不是很興奮,因為,我們可以在python程序中模擬網頁登錄,並且爬取網頁了!!!!!!
先看程序:
1 import http.cookiejar 2 import urllib.request 3 import urllib 4 #利用cookie模擬網站登錄 5 filenameOfCookie ='renren_cookie.txt' 6 cookie=http.cookiejar.MozillaCookieJar(filenameOfCookie) 7 headler=urllib.request.HTTPCookieProcessor(cookie) 8 opener=urllib.request.build_opener(headler) 9 data={"email":"18349366304","password":"XXXXXXXXXX"} 10 postdata=urllib.parse.urlencode(data).encode(encoding='UTF8') 11 loginurl='http://www.renren.com/PLogin.do' 12 request=opener.open(loginurl,postdata) 13 print (request) 14 cookie.save(ignore_discard=True, ignore_expires=True) 15 geturl='http://friend.renren.com/managefriends' 16 result=opener.open(geturl).read().decode('utf-8') 17 print (result) 18 filenameOfHtml ='renren.html' 19 fileToWrite=open(filenameOfHtml,'w') 20 fileToWrite.write(result) 21 fileToWrite.close()
看到了嗎,我們首先使用了MozillaCookieJar等工具來創建了cookie之后創建了opener來承載我們的處理引擎,之后就是重點了,我們偽造cookie的post數據,也就是data={"email":"18349366304","password":"XXXXXXXXXX"},因此我們就可以模擬輸入賬戶密碼登錄了,前面的工作就是為了這一步,經過一些編碼處理之后,我們通過request=opener.open(loginurl,postdata)來真正的將這些信息應用到具體的數據包中,模擬瀏覽器進行登錄,最后我們將獲得的cookie信息保存起來,寫入文本文件中。並且為了測試,我們訪問了一個不登錄就不能訪問的網頁,抓取了這個網頁的信息打印並寫入本地,程序結束。運行結果如圖:

不信的話,我們進入人人網的這個鏈接http://friend.renren.com/managefriends來看一下:可以看到結果完全一樣!!!

順便可以看一下,我們退出了就進不去這個網頁了,點擊回車顯示需要登錄:

難點三:如何攻破https格式的網頁登錄。
這里我用淘寶網進行測試。得到的效果是時好時壞,正在不斷地優化,淘寶網也是沒有驗證碼的。不過對於這種失敗,我覺得是應該的,要是這么容易就讓我蒙混過關了,我都有點不敢用了呢,吶吶~~~這里首先是https協議,我們的fiddler如果不經過配置都不能識別,更不說去解析了,於是我們首先要讓fiddler拿到操縱https包的優先權,於是我們需要提升權限,只能用證書的方式了,讓fiddler自動生成根證書然后安裝到瀏覽器中,這樣我們就可以抓取信息了。過程如下:

在工具中找到該窗口,選中那兩個對號,然后點擊actions,選擇“truest root certificate”選擇yes,



之后一直確認,然后點擊actions的導出到桌面:我們可以在桌面上看到相應的根證書了。


然后我們將證書導入到瀏覽器:在火狐中我們選擇證書,如圖所示:


在查看證書的導入中,將證書導入瀏覽器,之后就可以抓取https的包了,讓我們抓取淘寶網。

好了,我們找到了用戶名的post,那么密碼為什么是空的呢,我們繼續往下查找,總算找到了TPL_passwprd_2這個東西,這就是我們的密碼了,這也是一種安全策略吧。

讓我們用程序測試一下:
1 import urllib.request 2 import urllib 3 import http.cookiejar 4 filename = 'taobao_cookie.txt' 5 cookie = http.cookiejar.MozillaCookieJar(filename) 6 headler = urllib.request.HTTPCookieProcessor(cookie) 7 opener = urllib.request.build_opener(headler) 8 data = {"TPL_username": "朱彥榮0716", "TPL_password_2": "XXXXXXXXXX"} # 你的用戶名密碼 9 postdata = urllib.parse.urlencode(data).encode(encoding='UTF8') 10 loginurl = 'https://login.taobao.com/member/login.jhtml?' 11 request = opener.open(loginurl, postdata) 12 print('登錄成功!!!') 13 cookie.save(ignore_discard=True, ignore_expires=True) 14 geturl='https://i.taobao.com/my_taobao.htm?' 15 geturl='http://mm.taobao.com/687471686.htm' 16 result=opener.open(geturl) 17 print (result.read().decode('gbk','ignore'))
結果沒成功,這波土我吃的服!

不過這不代表沒辦法進去了,我們還可以用PlantomJS+Selenium來真正的模擬一個人的登錄過程來測試,這里需要慢慢學習,可以說這只是第一步罷了,就算進去了也破壞不了系統的什么東西的。
難點四、如何保存cookie,在以后的登錄中讀取cookie即可?
代碼如下:
1 import http.cookiejar 2 3 import urllib.request 4 5 import urllib 6 7 #創建MozillaCookieJar實例對象 8 9 cookie = http.cookiejar.MozillaCookieJar() 10 11 #從文件中讀取cookie內容到變量 12 13 cookie.load('renren_cookie.txt', ignore_discard=True, ignore_expires=True) 14 15 #創建請求的request 16 17 req = urllib.request.Request("http://friend.renren.com/managefriends") 18 19 #利用urllib2的build_opener方法創建一個opener 20 21 opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cookie)) 22 23 response = opener.open(req) 24 25 print (response.read().decode('utf-8','ignore'))
關於爬蟲的心得就先到這里為止!!!!!!
