python微博爬蟲
⑴ python網路爬蟲怎麼學習
現行環境下,大數據與人工智慧的重要依託還是龐大的數據和分析採集,類似於淘寶 京東 網路 騰訊級別的企業 能夠通過數據可觀的用戶群體獲取需要的數據,而一般企業可能就沒有這種通過產品獲取數據的能力和條件,想從事這方面的工作,需掌握以下知識:
1. 學習Python基礎知識並實現基本的爬蟲過程
一般獲取數據的過程都是按照 發送請求-獲得頁面反饋-解析並且存儲數據 這三個流程來實現的。這個過程其實就是模擬了一個人工瀏覽網頁的過程。
Python中爬蟲相關的包很多:urllib、requests、bs4、scrapy、pyspider 等,我們可以按照requests 負責連接網站,返回網頁,Xpath 用於解析網頁,便於抽取數據。
2.了解非結構化數據的存儲
爬蟲抓取的數據結構復雜 傳統的結構化資料庫可能並不是特別適合我們使用。我們前期推薦使用MongoDB 就可以。
3. 掌握一些常用的反爬蟲技巧
使用代理IP池、抓包、驗證碼的OCR處理等處理方式即可以解決大部分網站的反爬蟲策略。
4.了解分布式存儲
分布式這個東西,聽起來很恐怖,但其實就是利用多線程的原理讓多個爬蟲同時工作,需要你掌握 Scrapy + MongoDB + Redis 這三種工具就可以了。
⑵ 怎樣用python爬新浪微博大V所有數據
先上結論,通過公開的api如果想爬到某大v的所有數據,需要滿足以下兩個條件:
1、在你的爬蟲開始運行時,該大v的所有微博發布量沒有超過回溯查詢的上限,新浪是2000,twitter是3200。
2、爬蟲程序必須不間斷運行。
新浪微博的api基本完全照搬twitter,其中介面的參數特性與底層的Nosql密不可分,建議先看點Nosql資料庫的設計理念有助於更好的理解api設計。
一般來說,如果決定爬某個大v,第一步先試獲取該用戶的基本信息,中間會包含一條最新的status,記下其中的id號作為基準,命名為baseId。
介面中最重要的兩個參數:
since_id:返回ID比since_id大的微博(即比since_id時間晚的微博),默認為0。
max_id:返回ID小於或等於max_id的微博,默認為0。
出於各種原因,獲取statuses的介面,固定為按id降序排列(scan_index_forward=false),即最新的statuses返回在前。假設該微博第一天上線,就一個用戶,發了一百條,id是1到100。而你在該用戶發了第50條的時候開始運行的爬蟲,即baseId=50。
⑶ 怎樣用python爬新浪微博大V所有數據
先上結論,通過公開的api如果想爬到某大v的所有數據,需要滿足以下兩個條件:
1、在你的爬蟲開始運行時,該大v的所有微博發布量沒有超過回溯查詢的上限,新浪是2000,twitter是3200。
2、爬蟲程序必須不間斷運行。
新浪微博的api基本完全照搬twitter,其中介面的參數特性與底層的NoSQL密不可分,建議先看點Nosql資料庫的設計理念有助於更好的理解api設計。
一般來說,如果決定爬某個大v,第一步先試獲取該用戶的基本信息,中間會包含一條最新的status,記下其中的id號作為基準,命名為baseId。
介面中最重要的兩個參數:
since_id:返回ID比since_id大的微博(即比since_id時間晚的微博),默認為0。
max_id:返回ID小於或等於max_id的微博,默認為0。
出於各種原因,獲取statuses的介面,固定為按id降序排列(scan_index_forward=false),即最新的statuses返回在前。假設該微博第一天上線,就一個用戶,發了一百條,id是1到100。而你在該用戶發了第50條的時候開始運行的爬蟲,即baseId=50。
假設按每次獲取10條歷史數據遞歸,先將max_id設為baseId,獲取該用戶id為41-50的微博,再將max_id設為41重復循環,直到返回微博數量為1或0。這步沒有問題。
獲取用戶最新的statuses就有些蛋疼了,since_id=50,同樣獲取10條數據,返回的並不是id值為51-60的數據,而是100-91的數據。簡單說就是你沒法從since_id逐步更新到用戶當前status,而是得一口氣從用戶當前status更新到上次爬蟲運行時得到的最後一條status。假設你的爬蟲一個月才運行一次,該用戶在這期間發了2300條微博,根據限制你只能更新2000條,這其中最老的300條在你的系統內就會出現「斷檔」。
最後一條,以上只針對公開的api,stackoverflow上twitter
API可以申請許可權突破數量限制和更改排序機制,微博也應該有類似機制。
⑷ python爬蟲編碼問題
<span style="font-size:18px;">./s //在終端中運行程序
Current directory is :/home/talk8/CExample //通過API得到當前工作目錄
./s pwd //在終端中運行程序,第二個參數是pwd,表示讓程序執行pwd命令
/home/talk8/CExample //通過execlp得到當前工作目錄
⑸ Python爬網頁
1、網路爬蟲基本原理
傳統爬蟲從一個或若干初始網頁的URL開始,獲得初始網頁上的URL,在抓取網頁的過程中,不斷從當前頁面上抽取新的URL放入隊列,直到滿足系統的一定
停止條件。聚焦爬蟲的工作流程較為復雜,需要根據一定的網頁分析演算法過濾與主題無關的鏈接,保留有用的鏈接並將其放入等待抓取的URL隊列。然後,它將根
據一定的搜索策略從隊列中選擇下一步要抓取的網頁URL,並重復上述過程,直到達到系統的某一條件時停止。
2、設計基本思路
正如你所說,先到微博登陸頁面模擬登錄,抓取頁面,從頁面中找出所有URL,選擇滿足要求的URL文本說明,模擬點擊這些URL,重復上面的抓取動作,直到滿足要求退出。
3、現有的項目
google project網站有一個項目叫做sinawler,就是專門的新浪微博爬蟲,用來抓取微博內容。網站上不去,這個你懂的。不過可以網路一下「python編寫的新浪微博爬蟲(現在的登陸方法見新的一則微博)「,可以找到一個參考的源碼,他是用python2寫的。如果用python3寫,其實可以使用urllib.request模擬構建一個帶cookies的瀏覽器,省去對cookies的處理,代碼可以更加簡短。
4、此外
看下網路爬蟲的網路,裡面很多比較深入的內容,比如演算法分析、策略體系,會大有幫助,從理論角度提升代碼的技術層次。
⑹ python 新浪微博爬蟲,求助
0x00. 起因
因為參加學校大學生創新競賽,研究有關微博博文表達的情緒,需要大量微博博文,而網上無論是國內的某度、csdn,還是國外谷歌、gayhub、codeproject等都找不到想要的程序,沒辦法只能自己寫一個程序了。
ps.在爬盟找到類似的程序,但是是windows下的,並且閉源,而且最終爬取保存的文件用notepad++打開有很多奇怪的問題,所以放棄了。
0x01. 基礎知識
本程序由Python寫成,所以基本的python知識是必須的。另外,如果你有一定的計算機網路基礎,在前期准備時會有少走很多彎路。
對於爬蟲,需要明確幾點:
1. 對爬取對象分類,可以分為以下幾種:第一種是不需要登錄的,比如博主以前練手時爬的中國天氣網,這種網頁爬取難度較低,建議爬蟲新手爬這類網頁;第二種是需要登錄的,如豆瓣、新浪微博,這些網頁爬取難度較高;第三種獨立於前兩種,你想要的信息一般是動態刷新的,如AJAX或內嵌資源,這種爬蟲難度最大,博主也沒研究過,在此不細舉(據同學說淘寶的商品評論就屬於這類)。
2. 如果同一個數據源有多種形式(比如電腦版、手機版、客戶端等),優先選取較為「純凈的」展現。比如新浪微博,有網頁版,也有手機版,而且手機版可以用電腦瀏覽器訪問,這時我優先選手機版新浪微博。
3. 爬蟲一般是將網頁下載到本地,再通過某些方式提取出感興趣的信息。也就是說,爬取網頁只完成了一半,你還要將你感興趣的信息從下載下來的html文件中提取出來。這時就需要一些xml的知識了,在這個項目中,博主用的是XPath提取信息,另外可以使用XQuery等等其他技術,詳情請訪問w3cschool。
4. 爬蟲應該盡量模仿人類,現在網站反爬機制已經比較發達,從驗證碼到禁IP,爬蟲技術和反爬技術可謂不斷博弈。
0x02. 開始
決定了爬蟲的目標之後,首先應該訪問目標網頁,明確目標網頁屬於上述幾種爬蟲的哪種,另外,記錄為了得到感興趣的信息你需要進行的步驟,如是否需要登錄,如果需要登錄,是否需要驗證碼;你要進行哪些操作才能獲得希望得到的信息,是否需要提交某些表單;你希望得到的信息所在頁面的url有什麼規律等等。
以下博文以博主項目為例,該項目爬取特定新浪微博用戶從注冊至今的所有微博博文和根據關鍵詞爬取100頁微博博文(大約1000條)。
0x03. 收集必要信息
首先訪問目標網頁,發現需要登錄,進入登錄頁面如下新浪微博手機版登錄頁面
注意url後半段有很多形如」%xx」的轉義字元,本文後面將會講到。
從這個頁面可以看到,登錄新浪微博手機版需要填寫賬號、密碼和驗證碼。
這個驗證碼是近期(本文創作於2016.3.11)才需要提供的,如果不需要提供驗證碼的話,將有兩種方法進行登錄。
第一種是填寫賬號密碼之後執行js模擬點擊「登錄」按鈕,博主之前寫過一個Java爬蟲就是利用這個方法,但是現在找不到工程了,在此不再贅述。
第二種需要一定HTTP基礎,提交包含所需信息的HTTP POST請求。我們需要Wireshark 工具來抓取登錄微博時我們發出和接收的數據包。如下圖我抓取了在登錄時發出和接收的數據包Wireshark抓取結果1
在搜索欄提供搜索條件」http」可得到所有http協議數據包,右側info顯示該數據包的縮略信息。圖中藍色一行是POST請求,並且info中有」login」,可以初步判斷這個請求是登錄時發出的第一個數據包,並且這個180.149.153.4應該是新浪微博手機版登錄認證的伺服器IP地址,此時我們並沒有任何的cookie。
在序號為30是數據包中有一個從該IP發出的HTTP數據包,裡面有四個Set-Cookie欄位,這些cookie將是我們爬蟲的基礎。
Wireshark抓取結果2
早在新浪微博伺服器反爬機制升級之前,登錄是不需要驗證碼的,通過提交POST請求,可以拿到這些cookie,在項目源碼中的TestCookie.py中有示例代碼。
ps.如果沒有wireshark或者不想這么麻煩的話,可以用瀏覽器的開發者工具,以chrome為例,在登錄前打開開發者工具,轉到Network,登錄,可以看到發出和接收的數據,登錄完成後可以看到cookies,如下圖chrome開發者工具
接下來訪問所需頁面,查看頁面url是否有某種規律。由於本項目目標之一是獲取某用戶的全部微博,所以直接訪問該用戶的微博頁面,以央視新聞 為例。
央視新聞1
圖為央視新聞微博第一頁,觀察該頁面的url可以發現,新浪微博手機版的微博頁面url組成是 「weibo.cn/(displayID)?page=(pagenum)」 。這將成為我們爬蟲拼接url的依據。
接下來查看網頁源碼,找到我們希望得到的信息的位置。打開瀏覽器開發者工具,直接定位某條微博,可以發現它的位置,如下所示。
xpath
觀察html代碼發現,所有的微博都在<div>標簽里,並且這個標簽里有兩個屬性,其中class屬性為」c」,和一個唯一的id屬性值。得到這個信息有助於將所需信息提取出來。
另外,還有一些需要特別注意的因素
* 微博分為原創微博和轉發微博
* 按照發布時間至當前時間的差距,在頁面上有」MM分鍾前」、」今天HH:MM」、」mm月dd日 HH:MM」、」yyyy-mm-dd HH:MM:SS」等多種顯示時間的方式* 手機版新浪微博一個頁面大約顯示10條微博,所以要注意對總共頁數進行記錄以上幾點都是細節,在爬蟲和提取的時候需要仔細考慮。
0x04. 編碼
1.爬取用戶微博
本項目開發語言是Python 2.7,項目中用了一些第三方庫,第三方庫可以用pip的方法添加。
既然程序自動登錄的想法被驗證碼擋住了,想要訪問特定用戶微博頁面,只能使用者提供cookies了。
首先用到的是Python的request模塊,它提供了帶cookies的url請求。
import request
print request.get(url, cookies=cookies).content使用這段代碼就可以列印帶cookies的url請求頁面結果。
首先取得該用戶微博頁面數,通過檢查網頁源碼,查找到表示頁數的元素,通過XPath等技術提取出頁數。
頁數
項目使用lxml模塊對html進行XPath提取。
首先導入lxml模塊,在項目里只用到了etree,所以from lxml import etree
然後利用下面的方法返回頁數
def getpagenum(self):
url = self.geturl(pagenum=1)
html = requests.get(url, cookies=self.cook).content # Visit the first page to get the page number.
selector = etree.HTML(html)
pagenum = selector.xpath('//input[@name="mp"]/@value')[0]
return int(pagenum)
接下來就是不斷地拼接url->訪問url->下載網頁。
需要注意的是,由於新浪反爬機制的存在,同一cookies訪問頁面過於「頻繁」的話會進入類似於「冷卻期」,即返回一個無用頁面,通過分析該無用頁面發現,這個頁面在特定的地方會出現特定的信息,通過XPath技術來檢查這個特定地方是否出現了特定信息即可判斷該頁面是否對我們有用。
def ispageneeded(html):
selector = etree.HTML(html)
try:
title = selector.xpath('//title')[0]
except:
return False
return title.text != '微博廣場' and title.text != '微博'
如果出現了無用頁面,只需簡單地重新訪問即可,但是通過後期的實驗發現,如果長期處於過頻訪問,返回的頁面將全是無用頁面,程序也將陷入死循環。為了避免程序陷入死循環,博主設置了嘗試次數閾值trycount,超過這個閾值之後方法自動返回。
下面代碼片展示了單線程爬蟲的方法。
def startcrawling(self, startpage=1, trycount=20):
attempt = 0
try:
os.mkdir(sys.path[0] + '/Weibo_raw/' + self.wanted)except Exception, e:
print str(e)
isdone = False
while not isdone and attempt < trycount:
try:
pagenum = self.getpagenum()
isdone = True
except Exception, e:
attempt += 1
if attempt == trycount:
return False
i = startpage
while i <= pagenum:
attempt = 0
isneeded = False
html = ''
while not isneeded and attempt < trycount:
html = self.getpage(self.geturl(i))
isneeded = self.ispageneeded(html)
if not isneeded:
attempt += 1
if attempt == trycount:
return False
self.savehtml(sys.path[0] + '/Weibo_raw/' + self.wanted + '/' + str(i) + '.txt', html)print str(i) + '/' + str(pagenum - 1)
i += 1
return True
考慮到程序的時間效率,在寫好單線程爬蟲之後,博主也寫了多線程爬蟲版本,基本思想是將微博頁數除以線程數,如一個微博用戶有100頁微博,程序開10個線程,那麼每個線程只負責10個頁面的爬取,其他基本思想跟單線程類似,只需仔細處理邊界值即可,在此不再贅述,感興趣的同學可以直接看代碼。另外,由於多線程的效率比較高,並發量特別大,所以伺服器很容易就返回無效頁面,此時trycount的設置就顯得更重要了。博主在寫這篇微博的時候,用一個新的cookies,多線程爬取現場測試了一下爬取北京郵電大學的微博,3976條微博全部爬取成功並提取博文,用時僅15s,實際可能跟cookies的新舊程度和網路環境有關,命令行設置如下,命令行意義在項目網址里有說明python main.py _T_WM=xxx; SUHB=xxx; SUB=xxx; gsid_CTandWM=xxx u bupt m 20 20爬取的工作以上基本介紹結束,接下來就是爬蟲的第二部分,解析了。由於項目中提供了多線程爬取方法,而多線程一般是無序的,但微博博文是依靠時間排序的,所以項目採用了一種折衷的辦法,將下載完成的頁面保存在本地文件系統,每個頁面以其頁號為文件名,待爬取的工作結束後,再遍歷文件夾內所有文件並解析。
通過前面的觀察,我們已經了解到微博博文存在的標簽有什麼特點了,利用XPath技術,將這個頁面里所有有這個特點的標簽全部提取出來已經不是難事了。
在這再次提醒,微博分為轉發微博和原創微博、時間表示方式。另外,由於我們的研究課題僅對微博文本感興趣,所以配圖不考慮。
def startparsing(self, parsingtime=datetime.datetime.now()):
basepath = sys.path[0] + '/Weibo_raw/' + self.uidfor filename in os.listdir(basepath):
if filename.startswith('.'):
continue
path = basepath + '/' + filename
f = open(path, 'r')
html = f.read()
selector = etree.HTML(html)
weiboitems = selector.xpath('//div[@class="c"][@id]')for item in weiboitems:
weibo = Weibo()
weibo.id = item.xpath('./@id')[0]
cmt = item.xpath('./div/span[@class="cmt"]')if len(cmt) != 0:
weibo.isrepost = True
weibo.content = cmt[0].text
else:
weibo.isrepost = False
ctt = item.xpath('./div/span[@class="ctt"]')[0]
if ctt.text is not None:
weibo.content += ctt.text
for a in ctt.xpath('./a'):
if a.text is not None:
weibo.content += a.text
if a.tail is not None:
weibo.content += a.tail
if len(cmt) != 0:
reason = cmt[1].text.split(u'\xa0')
if len(reason) != 1:
weibo.repostreason = reason[0]
ct = item.xpath('./div/span[@class="ct"]')[0]
time = ct.text.split(u'\xa0')[0]
weibo.time = self.gettime(self, time, parsingtime)self.weibos.append(weibo.__dict__)
f.close()
方法傳遞的參數parsingtime的設置初衷是,開發前期爬取和解析可能不是同時進行的(並不是嚴格的「同時」),微博時間顯示是基於訪問時間的,比如爬取時間是10:00,這時爬取到一條微博顯示是5分鍾前發布的,但如果解析時間是10:30,那麼解析時間將錯誤,所以應該講解析時間設置為10:00。到後期爬蟲基本開發完畢,爬取工作和解析工作開始時間差距降低,時間差將是爬取過程時長,基本可以忽略。
解析結果保存在一個列表裡,最後將這個列表以json格式保存到文件系統里,刪除過渡文件夾,完成。
def save(self):
f = open(sys.path[0] + '/Weibo_parsed/' + self.uid + '.txt', 'w')jsonstr = json.mps(self.weibos, indent=4, ensure_ascii=False)f.write(jsonstr)
f.close()
2.爬取關鍵詞
同樣的,收集必要的信息。在微博手機版搜索頁面敲入」python」,觀察url,研究其規律。雖然第一頁並無規律,但是第二頁我們發現了規律,而且這個規律可以返回應用於第一頁第一頁
第二頁
應用後第一頁
觀察url可以發現,對於關鍵詞的搜索,url中的變數只有keyword和page(事實上,hideSearchFrame對我們的搜索結果和爬蟲都沒有影響),所以在代碼中我們就可以對這兩個變數進行控制。
另外,如果關鍵詞是中文,那麼url就需要對中文字元進行轉換,如我們在搜索框敲入」開心」並搜索,發現url如下顯示搜索開心
但復制出來卻為
http://weibo.cn/search/mblog?hideSearchFrame=&keyword=%E5%BC%80%E5%BF%83&page=1幸好,python的urllib庫有qoute方法處理中文轉換的功能(如果是英文則不做轉換),所以在拼接url前使用這個方法處理一下參數。
另外,考慮到關鍵詞搜索屬於數據收集階段使用的方法,所以在此只提供單線程下載網頁,如有多線程需要,大家可以按照多線程爬取用戶微博的方法自己改寫。最後,對下載下來的網頁進行提取並保存(我知道這樣的模塊設計有點奇怪,打算重(xin)構(qing)時(hao)時再改,就先這樣吧)。
def keywordcrawling(self, keyword):
realkeyword = urllib.quote(keyword) # Handle the keyword in Chinese.
try:
os.mkdir(sys.path[0] + '/keywords')
except Exception, e:
print str(e)
weibos = []
try:
highpoints = re.compile(u'[\U00010000-\U0010ffff]') # Handle emoji, but it seems doesn't work.
except re.error:
highpoints = re.compile(u'[\uD800-\uDBFF][\uDC00-\uDFFF]')pagenum = 0
isneeded = False
while not isneeded:
html = self.getpage('http://weibo.cn/search/mblog?keyword=%s&page=1' % realkeyword)isneeded = self.ispageneeded(html)
if isneeded:
selector = etree.HTML(html)
try:
pagenum = int(selector.xpath('//input[@name="mp"]/@value')[0])except:
pagenum = 1
for i in range(1, pagenum + 1):
try:
isneeded = False
while not isneeded:
html = self.getpage('http://weibo.cn/search/mblog?keyword=%s&page=%s' % (realkeyword, str(i)))isneeded = self.ispageneeded(html)
selector = etree.HTML(html)
weiboitems = selector.xpath('//div[@class="c"][@id]')for item in weiboitems:
cmt = item.xpath('./div/span[@class="cmt"]')if (len(cmt)) == 0:
ctt = item.xpath('./div/span[@class="ctt"]')[0]
if ctt.text is not None:
text = etree.tostring(ctt, method='text', encoding="unicode")tail = ctt.tail
if text.endswith(tail):
index = -len(tail)
text = text[1:index]
text = highpoints.sub(u'\u25FD', text) # Emoji handling, seems doesn't work.
weibotext = text
weibos.append(weibotext)
print str(i) + '/' + str(pagenum)
except Exception, e:
print str(e)
f = open(sys.path[0] + '/keywords/' + keyword + '.txt', 'w')try:
f.write(json.mps(weibos,indent=4,ensure_ascii=False))except Exception,ex:
print str(ex)
finally:
f.close()
博主之前從未寫過任何爬蟲程序,為了獲取新浪微博博文,博主先後寫了3個不同的爬蟲程序,有Python,有Java,爬蟲不能用了是很正常的,不要氣餒,爬蟲程序和反爬機制一直都在不斷博弈中,道高一尺魔高一丈。
另. 轉載請告知博主,如果覺得博主帥的話就可以不用告知了
⑺ 如何用Python寫一個分布式爬蟲
本文將會以PC端微博進行講解,因為移動端微博數據不如PC短全面,而且抓取和解析難度都會小一些。文章比較長,由於篇幅所限,文章並沒有列出所有代碼,只是講了大致流程和思路。
要抓微博數據,第一步便是模擬登陸,因為很多信息(比如用戶信息,用戶主頁微博數據翻頁等各種翻頁)都需要在登錄狀態下才能查看。關於模擬登陸進階,我寫過兩篇文章,一篇是模擬登陸微博的,是從小白的角度寫的。另外一篇是模擬登陸網路雲的,是從有一定經驗的熟手的角度寫的。讀了這兩篇文章,並且根據我寫的過程自己動手實現過的同學,應該對於模擬登陸PC端微博是沒有太大難度的。那兩篇文章沒有講如何處理驗證碼,這里我簡單說一下,做爬蟲的同學不要老想著用什麼機器學習的方法去識別復雜驗證碼,真的難度非常大,這應該也不是一個爬蟲工程師的工作重點,當然這只是我的個人建議。工程化的項目,我還是建議大家通過打碼平台來解決驗證碼的問題。我在分布式微博爬蟲中就是直接調用打碼平台的介面來做的大規模微博賬號的模擬登陸,效果還不錯,而且打碼成本很低。
說完模擬登陸(具體請參見我寫的那兩篇文章,篇幅所限,我就不過來了),我們現在正式進入微博的數據抓取。這里我會以微博用戶信息抓取為例來進行分析和講解。
關於用戶信息抓取,可能我們有兩個目的。一個是我們只想抓一些指定用戶,另外一個是我們想盡可能多的抓取更多數量的用戶的信息。我的目的假定是第二種。那麼我們該以什麼樣的策略來抓取,才能獲得盡可能多的用戶信息呢?如果我們初始用戶選擇有誤,選了一些不活躍的用戶,很可能會形成一個環,這樣就抓不了太多的數據。這里有一個很簡單的思路:我們把一些大V拿來做為種子用戶,我們先抓他們的個人信息,然後再抓大V所關注的用戶和粉絲,大V關注的用戶肯定也是類似大V的用戶,這樣的話,就不容易形成環了。
策略我們都清楚了。就該是分析和編碼了。
我們先來分析如何構造用戶信息的URL。這里我以微博名為一起神吐槽的博主為例進行分析。做爬蟲的話,一個很重要的意識就是爬蟲能抓的數據都是人能看到的數據,反過來,人能在瀏覽器上看到的數據,爬蟲幾乎都能抓。這里用的是幾乎,因為有的數據抓取難度特別。我們首先需要以正常人的流程看看怎麼獲取到用戶的信息。我們先進入該博主的主頁,如下圖
根據唯一性判斷
我們在頁面源碼中搜索,只發現一個script中有該字元串,那麼就是那段script是頁面相關信息。我們可以通過正則表達式把該script提取出來,然後把其中的html也提取出來,再保存到本地,看看信息是否全面。這里我就不截圖了。感覺還有很多要寫的,不然篇幅太長了。
另外,對於具體頁面的解析,我也不做太多的介紹了。太細的東西還是建議讀讀源碼。我只講一下,我覺得的一種處理異常的比較優雅的方式。微博爬蟲的話,主要是頁面樣式太多,如果你打算包含所有不同的用戶的模版,那麼我覺得幾乎不可能,不同用戶模版,用到的解析規則就不一樣。那麼出現解析異常如何處理?尤其是你沒有catch到的異常。很可能因為這個問題,程序就崩掉。其實對於Python這門語言來說,我們可以通過裝飾器來捕捉我們沒有考慮到的異常,比如我這個裝飾器
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
def parse_decorator(return_type):
"""
:param return_type: 用於捕捉頁面解析的異常, 0表示返回數字0, 1表示返回空字元串, 2表示返回[],3表示返回False, 4表示返回{}, 5返回None
:return: 0,'',[],False,{},None
"""
def page_parse(func):
@wraps(func)
def handle_error(*keys):
try:
return func(*keys)
except Exception as e:
parser.error(e)
if return_type == 5:
return None
elif return_type == 4:
return {}
elif return_type == 3:
return False
elif return_type == 2:
return []
elif return_type == 1:
return ''
else:
return 0
return handle_error
return page_parse
上面的代碼就是處理解析頁面發生異常的情況,我們只能在數據的准確性、全面性和程序的健壯性之間做一些取捨。用裝飾器的話,程序中不用寫太多的try語句,代碼重復率也會減少很多。
頁面的解析由於篇幅所限,我就講到這里了。沒有涉及太具體的解析,其中一個還有一個比較難的點,就是數據的全面性,讀者可以去多觀察幾個微博用戶的個人信息,就會發現有的個人信息,有的用戶有填寫,有的並沒有。解析的時候要考慮完的話,建議從自己的微博的個人信息入手,看到底有哪些可以填。這樣可以保證幾乎不會漏掉一些重要的信息。
最後,我再切合本文的標題,講如何搭建一個分布式的微博爬蟲。開發過程中,我們可以先就做單機單線程的爬蟲,然後再改成使用celery的方式。這里這樣做是為了方便開發和測試,因為你單機搭起來並且跑得通了,那麼分布式的話,就很容易改了,因為celery的API使用本來就很簡潔。
我們抓取的是用戶信息和他的關注和粉絲uid。用戶信息的話,我們一個請求大概能抓取一個用戶的信息,而粉絲和關注我們一個請求可以抓取18個左右(因為這個抓的是列表),顯然可以發現用戶信息應該多佔一些請求的資源。這時候就該介紹理論篇沒有介紹的關於celery的一個高級特性了,它叫做任務路由。直白點說,它可以規定哪個分布式節點能做哪些任務,不能做哪些任務。它的存在可以讓資源分配更加合理,分布式微博爬蟲項目初期,就沒有使用任務路由,然後抓了十多萬條關注和分析,結果發現用戶信息抓幾萬條,這就是資源分配得不合理。那麼如何進行任務路由呢?
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# coding:utf-8
import os
from datetime import timedelta
from celery import Celery
from kombu import Exchange, Queue
from config.conf import get_broker_or_backend
from celery import platforms
# 允許celery以root身份啟動
platforms.C_FORCE_ROOT = True
worker_log_path = os.path.join(os.path.dirname(os.path.dirname(__file__))+'/logs', 'celery.log')
beat_log_path = os.path.join(os.path.dirname(os.path.dirname(__file__))+'/logs', 'beat.log')
tasks = ['tasks.login', 'tasks.user']
# include的作用就是注冊服務化函數
app = Celery('weibo_task', include=tasks, broker=get_broker_or_backend(1), backend=get_broker_or_backend(2))
app.conf.update(
CELERY_TIMEZONE='Asia/Shanghai',
CELERY_ENABLE_UTC=True,
CELERYD_LOG_FILE=worker_log_path,
CELERYBEAT_LOG_FILE=beat_log_path,
CELERY_ACCEPT_CONTENT=['json'],
CELERY_TASK_SERIALIZER='json',
CELERY_RESULT_SERIALIZER='json',
CELERY_QUEUES=(
Queue('login_queue', exchange=Exchange('login', type='direct'), routing_key='for_login'),
Queue('user_crawler', exchange=Exchange('user_info', type='direct'), routing_key='for_user_info'),
Queue('fans_followers', exchange=Exchange('fans_followers', type='direct'), routing_key='for_fans_followers'),
)
上述代碼我指定了有login_queue、user_crawler、fans_followers三個任務隊列。它們分別的作用是登錄、用戶信息抓取、粉絲和關注抓取。現在假設我有三台爬蟲伺服器A、B和C。我想讓我所有的賬號登錄任務分散到三台伺服器、讓用戶抓取在A和B上執行,讓粉絲和關注抓取在C上執行,那麼啟動A、B、C三個伺服器的celery worker的命令就分別是
Python
1
2
3
celery -A tasks.workers -Q login_queue,user_crawler worker -l info -c 1 # A伺服器和B伺服器啟動worker的命令,它們只會執行登錄和用戶信息抓取任務
celery -A tasks.workers -Q login_queue,fans_followers worker -l info -c 1 # C伺服器啟動worker的命令,它只會執行登錄、粉絲和關注抓取任務
然後我們通過命令行或者代碼(如下)就能發送所有任務給各個節點執行了
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
4
⑻ 如何寫爬蟲程序爬取豆瓣網或者新浪微博里的內容
在面向對象的高級語言中,早已有人將http請求封裝成了類庫,你只需要調下介面,就能獲得目標網頁的源碼。所以程序需要做的就是請求目標url,獲取頁面的源碼,解析html。基本流程是:
獲取目標頁面源碼,方法:調用對應的類庫。
解析html文件,提取出自己想要的信息。方法:正則表達式或者解析html的庫。
按照上述步驟,C++(Qt)涉及的類是:
WebView,它的內核其實就是webkit,所以它就是一個功能原始的瀏覽器,他內置能夠返回頁面源碼的函數,接受一個url的string類型參數,返回一個QString對象。
WebView類有方法能夠處理DOM。
C#(.net)涉及的類是:
WebClient,WebRequest,HttpWebRequest等類,第一個封裝得比較高級,寫法簡單,後面兩個封裝得低級,寫起來麻煩但是用起來靈活,HttpWebRequest是WebRequest的一個子類。
Html Agility Pack。
Python涉及的包是:
urllib,urllib2,前者僅可以接受URL,不能偽裝Header,但是需要用它的一個函數對post數據進行編碼。類似於瀏覽器的有Selenium。
BeautifulSoup。
上面三種相比,python寫法最簡單,操作也靈活,要獲取源碼只要寫一句話就行。字元串處理python也毫不遜色於C#和C++。
⑼ pythonpyautogui是爬蟲嗎
是。PyAutoGui是一個跨平台GUI自動化庫。PyAutoGUI是一個Python模塊,用於以編程方式控制滑鼠和鍵盤。Python網路爬蟲,pyautogui與pytesseract抓取新浪微博數據,OCR方案用ocr與pyautogui,以及webbrowser實現功能:設計爬蟲抓取新浪微博數據,比如,抓取微博用戶的粉絲數。