當前位置:編程學習大全網 - 源碼下載 - 新浪分享源代碼

新浪分享源代碼

0x00。原因

因為要參加大學生的創新大賽,研究微博的博文所表達的情感,需要大量的微博的博文,而且無論是國內的某個學位,csdn,還是國外的Google,gayhub,codeproject,都找不到想要的程序,只好自己寫程序了。

贊美詩我在《攀登聯盟》裏找到壹個類似的程序,不過是在windows下,源碼是關閉的。而且爬取保存的文件,用notepad++打開,出現了很多奇怪的問題,我就放棄了。

0x001。基礎知識

這個程序是用python寫的,所以基本的Python知識是必須的。另外,如果妳有壹定的計算機網絡基礎,在前期準備的時候會少走很多彎路。

對於爬行動物,妳需要明確以下幾點:

1.爬取對象的分類可以分為以下幾類:第壹類是不需要登錄的,比如博主以前練手的時候爬的中國天氣網。這類網頁很難抓取,建議爬蟲新手爬這類網頁;二是登錄,如豆瓣、新浪微博,難爬;第三種獨立於前兩種,妳想要的信息壹般是動態刷新的,比如AJAX或者嵌入式資源。這種爬蟲是最難的,博主也沒研究過,這裏就不細說了(據同學說,淘寶的商品評論就屬於這壹類)。

2.如果同壹個數據源有多種形式(如電腦版、手機版、客戶端等。),更“純粹”的呈現方式更受青睞。比如新浪微博有網頁版和手機版,手機版可以通過電腦瀏覽器訪問。這個時候,我更喜歡手機版的新浪微博。

3.爬蟲壹般是把網頁下載到本地,然後通過某種方式提取感興趣的信息。換句話說,抓取網頁只是完成了壹半,妳需要從下載的html文件中提取妳感興趣的信息。這時候就需要壹些xml的知識了。在這個項目中,博客作者使用XPath提取信息,也可以使用XQuery等其他技術。詳情請訪問w3cschool。

4.爬蟲要盡可能模仿人類。現在網站的反抓取機制已經開發出來了。從驗證碼到IP禁止,爬蟲技術和反爬蟲技術可謂是連續博弈。

0x02。去

確定爬蟲的目標後,首先要訪問目標網頁,了解目標網頁屬於以上哪種爬蟲。另外,記錄下妳需要采取的步驟,才能得到妳感興趣的信息,比如是否需要登錄,如果需要登錄,是否需要驗證碼;妳需要做什麽才能得到妳想要的信息,是否需要提交壹些表格;妳想要的信息所在頁面的url有什麽規則等等。

以下博文以blogger項目為例。該項目抓取特定新浪微博用戶自註冊以來的所有微博博文,按關鍵詞抓取100頁微博博文(約1000篇)。

0x03。收集必要的信息

首先訪問目標網頁,發現需要登錄。進入登錄頁面如下:新浪微博手機版登錄頁面。

註意,在url的後半部分有許多像“%xx”這樣的轉義字符,這將在本文後面討論。

從這個頁面可以看到,登錄新浪微博手機版需要填寫賬號、密碼和驗證碼。

這個驗證碼只需要最近提供(本文創建於2016.3.11)。如果不需要提供驗證碼,會有兩種登錄方式。

第壹種方法是進行js模擬,填寫賬號密碼後點擊“登錄”按鈕。博主之前用這個方法寫了壹個Java爬蟲,現在找不到項目了,這裏就不贅述了。

第二種需要壹定的HTTP基礎,提交包含所需信息的HTTP POST請求。我們需要Wireshark工具來捕獲我們在登錄微博時發送和接收的數據包。如下圖所示,我抓取了登錄時收發的數據包。Wireshark搶到了1的結果。

在搜索欄中提供搜索條件"/(displayID)?page=(pagenum)" .這將是我們的爬蟲拼接url的基礎。

接下來看網頁的源代碼,找到我們想要的信息的位置。打開瀏覽器開發者工具,直接定位壹個微博,就可以找到它的位置,如下圖。

xpath

觀察html代碼,發現所有微博都在< div & gt標簽,這個標簽中有兩個屬性,其中class屬性是“c”和壹個唯壹的id屬性值。獲取這些信息有助於提取所需的信息。

此外,還有壹些因素需要特別註意。

*微博分為原創微博和轉發微博。

*根據發布時間與當前時間的不同,頁面上顯示時間的方式有多種,如“MM分鐘前”、“今天的HH:MM”、“MM月dd日HH:MM-DD hh: mm: SS”。*手機版新浪微博壹頁顯示約10條微博,註意總量* *。

0x04。編碼

1.抓取用戶微博

這個項目的開發語言是Python 2.7,項目中使用了壹些第三方庫,可以通過pip添加。

由於驗證碼阻擋了自動登錄的思路,用戶要訪問特定用戶的微博頁面,只能提供cookies。

第壹個是Python的請求模塊,它提供帶有cookies的url請求。

導入請求

打印請求。get (url,cookies = cookies)。內容使用此代碼打印帶有cookies的URL請求頁面結果。

首先,獲取用戶的微博頁面數量。通過檢查網頁的源代碼,找到代表頁數的元素,通過XPath等技術提取頁數。

頁數

該項目使用lxml模塊通過XPath提取html。

首先,導入lxml模塊,項目中只使用etree,所以從lxml導入etree。

然後用下面的方法返回頁碼。

def getpagenum(self):

URL = self . geturl(pagenum = 1)

html = requests.get(url,cookies=self.cook)。內容#訪問第壹頁獲取頁碼。

選擇器= etree。HTML(html)

pagenum = selector . XPath('//input[@ name = " MP "]/@ value ')[0]

return int(pagenum)

下壹步是連續拼接網址->訪問網址-& gt;下載網頁。

需要註意的是,由於新浪反爬取機制的存在,如果同壹個cookies訪問頁面過於頻繁,就會進入類似的“冷靜期”,即會返回壹個無用的頁面。通過分析這個無用的頁面,發現這個頁面在特定的地方會有特定的信息,這個頁面對我們是否有用可以通過XPath技術來判斷。

def ispageneeded(html):

選擇器= etree。HTML(html)

嘗試:

title = selector . XPath('//title ')[0]

除了:

返回False

返回title.text!= '微博廣場'和title.text!= '微博'

如果有無用的頁面,妳只需要再次訪問它們。但是通過後來的實驗發現,如果長時間頻繁訪問它們,那麽返回的頁面都是無用的,程序會陷入死循環。為了防止程序陷入死循環,博主設置了壹個trycount閾值,超過閾值後方法會自動返回。

下面的代碼片段展示了單線程爬蟲的方法。

def startcrawling(self,startpage=1,trycount=20):

嘗試= 0

嘗試:

OS . mkdir(sys . path[0]+'/Weibo _ raw/'+self . wanted)除了例外,e:

打印字符串(e)

isdone = False

while not isdone並嘗試& lt嘗試計數:

嘗試:

pagenum = self.getpagenum()

isdone = True

除了例外,e:

嘗試+= 1

if attempt == trycount:

返回False

i =起始頁

而我& lt= pagenum:

嘗試= 0

isneeded = False

html = ' '

while not isneeded and attempt & lt嘗試計數:

html = self . getpage(self . geturl(I))

isneeded = self . ispageneeded(html)

如果不需要:

嘗試+= 1

if attempt == trycount:

返回False

self . save html(sys . path[0]+'/Weibo _ raw/'+self . wanted+'/'+str(I)+'。txt ',html)打印字符串(i) + '/' +字符串(pagenum - 1)

i += 1

返回True

考慮到程序的時間效率,在寫了單線程爬蟲之後,博主又寫了多線程爬蟲版本。基本思路是微博頁面數除以跟帖數。比如微博中的壹個用戶有100個微博頁面,程序有10個線程,那麽每個線程只負責爬取10個頁面。其他基本思路和單線程差不多,只有邊界值需要小心處理,這裏就不贅述了。另外,由於多線程的效率比較高,並發量特別大,服務器很容易返回無效頁面,所以trycount的設置比較重要。博主在寫這條微博的時候,用了壹個新的cookie來測試誰爬了北京郵電大學的微博。3976條微博文章全部成功爬取,博文提取。只用了15s,這其實可能和新舊cookies以及網絡環境有關。命令行設置如下,項目網站中解釋了命令行的含義:python main.py _ T _ WM = xxxSUHB = xxxSUB = xxxGSID _ CTANDWM = XXX UBUPPT M 20 20以上爬行工作的基本介紹結束,接下來分析爬蟲的第二部分。因為項目提供了多線程抓取的方法,而多線程壹般是亂序的,但是微博的博文是按時間排序的,所以項目采用了折中的方法,將下載的頁面保存在本地文件系統中,每個頁面以其頁碼作為文件名。爬行工作完成後,遍歷並解析文件夾中的所有文件。

通過前面的觀察,我們了解到了微博的博文都有哪些特點。通過使用XPath技術,從這個頁面中提取所有具有這個特性的標簽並不困難。

再次,微博分為轉發微博和原創微博,時間表達。另外,因為我們的研究課題只對微博文字感興趣,所以不考慮插圖。

def startparsing(self,parsing time = datetime . datetime . now()):

basepath = sys . path[0]+'/Weibo _ raw/'+self . uid for filename in OS . listdir(basepath):

if filename.startswith(' . '):

繼續

path = basepath + '/' + filename

f =打開(路徑,“r”)

html = f.read()

選擇器= etree。HTML(html)

weiboitems = selector . XPath('//div[@ class = " c "][@ id]')用於Weibo items中的項目:

微博=微博()

weibo.id = item.xpath('。/@id')[0]

cmt = item.xpath('。/div/span[@ class = " CMT "]')if len(CMT)!= 0:

weibo.isrepost = True

weibo.content = cmt[0]。文本

否則:

weibo.isrepost = False

ctt = item.xpath('。/div/span[@class="ctt"]')[0]

如果ctt.text不為None:

weibo.content += ctt.text

對於ctt.xpath中的。/a '):

如果a.text不是None:

微博.內容+= a.text

如果a.tail不為None:

weibo.content += a.tail

if len(cmt)!= 0:

reason = CMT[1]. text . split(u ' \ xa0 ')

if len(原因)!= 1:

Weibo . reportstroy = 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(微博。__字典_ _)

f.close()

方法傳遞的參數parsingtime的設置初衷是開發初期抓取和解析可能不會同時進行(並非嚴格意義上的“同時”),微博時間顯示以訪問時間為準,比如抓取時間為10:00,五分鐘前發布了壹條微博顯示,但如果解析時間為10:30,解析時間就會出錯,所以,到爬蟲基本發育結束,爬行和解析的開始時間差距會縮小,時間差就是爬行過程的時間,基本可以忽略。

解析結果保存在列表中。最後,列表以json格式保存到文件系統,並刪除轉換文件夾。

定義保存(自己):

f = open(sys . path[0]+'/Weibo _ parsed/'+self . uid+'。txt ',' w ')JSON str = JSON . dumps(self . weibos,indent=4,確保_ascii=False)f.write(jsonstr)

f.close()

抓取關鍵詞

同樣,收集必要的信息。在微博手機搜索頁面輸入“python”,觀察網址,研究其規律。雖然第壹頁沒有規則,但是我們在第二頁發現了壹個規則,這個規則可以應用回第壹頁。

第二頁

申請後的第壹頁

觀察url可以發現,url中唯壹的變量是關鍵字和頁面(其實hideSearchFrame對我們的搜索結果和爬蟲沒有影響),所以我們可以在代碼中控制這兩個變量。

另外,如果關鍵詞是中文,那麽網址需要轉換漢字。例如,如果我們在搜索框中鍵入“Happy”進行搜索,我們發現url顯示Happy Search如下。

但是它被復制為

/search/mblog?hideSearchFrame = & amp關鍵字= % E5 % BC % 80 % E5 % BF % 83 & ampPage=1好在python的urllib庫有qoute方法處理中文轉換的功能(如果是英文就不轉換了),所以在拼接URL之前用這個方法處理參數。

另外,考慮到關鍵詞搜索屬於數據收集階段使用的方法,我們這裏只提供網頁的單線程下載。如果有多線程的需求,可以按照多線程抓取用戶微博的方法自己重寫。最後提取並保存下載的網頁(我知道這個模塊設計有點奇怪,所以打算重新創建的時候再改(郝),就這樣吧)。

def關鍵字爬網(self,keyword):

real keyword = URL lib . quote(keyword)#用中文處理關鍵字。

嘗試:

OS . mkdir(sys . path[0]+'/keywords ')

除了例外,e:

打印字符串(e)

微博= []

嘗試:

high points = re . compile(u '[\ u 00010000-\ u 0010 ffff]')#處理表情符號,但是好像不管用。

除了re.error:

high points = re . compile(u '[\ ud 800-\ uDBFF][\ UDC 00-\ uDFFF]')pagenum = 0

isneeded = False

當不需要時:

html = self . get page('/search/mblog?關鍵字= % s & amppage = 1 ' % real keyword)is needed = self . ispageneeded(html)

如果需要:

選擇器= etree。HTML(html)

嘗試:

pagenum = int(selector . XPath('//input[@ name = " MP "]/@ value ')[0])除了:

pagenum = 1

對於範圍內的I(1,pagenum + 1):

嘗試:

isneeded = False

當不需要時:

html = self . get page('/search/mblog?關鍵字= % s & amppage=%s' % (realkeyword,str(I)))is needed = self . ispageneeded(html)

選擇器= etree。HTML(html)

weiboitems = selector . XPath('//div[@ class = " c "][@ id]')用於Weibo items中的項目:

cmt = item.xpath('。/div/span[@ class = " CMT "]')if(len(CMT))= = 0:

ctt = item.xpath('。/div/span[@class="ctt"]')[0]

如果ctt.text不為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) #表情符號的處理方式,似乎行不通。

微博文本=文本

微博附加(微博文本)

打印字符串(i) + '/' +字符串(pagenum)

除了例外,e:

打印字符串(e)

f = open(sys . path[0]+'/keywords/'+keyword+'。txt ',' w ')嘗試:

f.write(json.dumps(weibos,indent=4,確保_ ascii = False))Exception除外,例如:

打印字符串(ex)

最後:

f.close()

博客作者以前從來沒有寫過任何爬蟲程序。為了獲取新浪微博博文,博主們編寫了三種不同的爬蟲程序,包括Python和Java。爬行動物不能用很正常。不要氣餒。爬蟲程序和反爬行機制壹直在不斷博弈。

另外,轉載請告知博主,如果妳認為博是老板就不需要告知。

  • 上一篇:在這臺機器上測試ASP程序,但是SQL數據庫,怎麽辦?
  • 下一篇:怎麽把小米手環步數上傳到微信
  • copyright 2024編程學習大全網