這段時間發現越來越痴迷於python,特別是python3,所以一邊看書,一邊就想動手做點實踐。由於實驗室有收集新聞語料的需求,所以就想著以鳳凰網新聞**為目標,試著寫乙個爬蟲如何? 結果還真實現了! 當然 只是入門級的哦,請各位看官多提意見。
工具:python3, beautiful soup4
基本思想:先給定乙個目標url,它應該是乙個索引型別頁面(如然後以廣度優先的思路 去分析這個url中包含的具體新聞頁面鏈結和其它索引頁面鏈結的頁面。接著以迭代的思想,獲取其下層索引頁面中包含的所有新聞頁面鏈結和索引頁面鏈結,直至當前站下索引頁面都處理完。最後提取具體新聞頁面的內容
原理圖:
具體**:
說明:如果只考慮收集頁面url而不考慮抓取其中的內容,那麼可以無視getcontent()方法。 由於本人希望能夠抓取具體的新聞內容,而且只是實驗該方法的可行性,所以選取了範圍較小的鳳凰國際新聞,根據鳳凰新聞具體標籤結構來識別其中的時間、標題、正文等。也就是說,如果要抓取其它**內容的話,getcontent()方法中的目標標籤也要作相應的修改。本人尚未嘗試。
from urllib.request import urlopen
from bs4 import beautifulsoup
import time
#所需變數初始化及準備工作
#記錄程式開始時間
start = time.clock()
#建立乙個list用於儲存要抽取的**
rooturl=input('請輸入起始目錄**:')
#建立乙個list用於儲存索引型頁面的url
indexlist=
#建立乙個list用於儲存具體內容頁面的url
pagelist=
##********************以下為方法********************====##
'''方法名:parsehref
作用:從引數給定的url中解析出其中包含的索引類url和具體頁面類url,並分別儲存到不同的list中,同時確保值唯一
引數:'''
#獲取解析結果
def parsehref(url):
rawtext=urlopen(url).read() #抓取當前頁面
soup = beautifulsoup(rawtext) #使用bs模組獲取其結構樹
newslinks=soup.findall("a") #從中找到所有鏈結標籤
for a in newslinks: #迴圈處理所有a標籤
currentlink=a.get('href') #獲取當前標籤的鏈結位址
if currentlink.find('detail_')>0: # 如果位址中含有detail_子串,說明這是乙個具體頁面
if currentlink in pagelist: #判斷該頁面在pagelist中是否存在 如果存在
print(' 位址已經存在,不處理') # 不處理
else: #如果不存在
pagelist.extend([currentlink]) #則新增進去
print('具體頁面list新增:',currentlink)
elif currentlink.endswith('/'): 如果當前位址是以/結尾,說明這是乙個索引頁面,也就是說它下面還有下級頁面
if currentlink in indexlist: # 判斷該頁面在indexlist中是否存在 如果存在
print(' 位址已經存在,不處理') #不處理
else: # 如果不存在,
indexlist.extend([currentlink]) # 則新增進去
print('索引頁面list新增:',currentlink)
'''方法名:getcontent
作用:從pagelist中的url中解析出時間、標題、正文內容,並儲存到本地文字中
引數:無引數
'''def getcontent():
#解析當前pagelist列表中儲存的所有具體內容頁面
print('解析具體頁面')
for p in pagelist:
currentpage=urlopen(p).read()
currenttext=beautifulsoup(currentpage)
print(p)
#獲取新聞發布時間
newstime=currenttext.find('span',)
if newstime:
newstime=newstime.get_text().replace('年','-')
newstime=newstime.replace('月','-')
newstime=newstime.replace('日','')
newstime=newstime.replace(':',':')
#獲取新聞標題
newstitle=currenttext.find("h1")
if len(newstitle)>0:
#print(newstitle.get_text())
newstitle=newstitle.get_text().replace('\t','')
newstitle=newstitle.replace('/','/')
#獲取新聞正文
newscontent= currenttext.find(id="main_content" )
if newscontent:
#以時間和標題為檔名,建立txt檔案,並寫入正文內容
f=open('file/'+newstime+" "+newstitle+'.txt','w+', encoding='utf-8')
f.write(newscontent.get_text())
print(newstime+" "+newstitle+'.txt')
f.close()
print('處理完成:',len(pagelist),'個頁面。')
#開始爬取
# 1、先解析根目錄
print('解析根目錄')
parsehref(rooturl)
print('根目錄解析完成')
# 2、分析indexlist中的值迭代進行解析,直至所有索引頁面都被分析過
print('解析獲取的索引頁面')
for i in indexlist:
parsehref(i)
print('索引頁面解析完成')
#3、解析pagelist中所有具體頁面
getcontent()
#4、計算程式執行過程耗時
end = time.clock()
print (end-start)
結果截圖:
一種快速的未登陸詞識別方法 原理和實現
一種快速的未登陸詞識別方法 原理和實現 最近網路上關於分詞的演算法已經很多了,在實際應用中每個人根據對分詞的不同理解寫了不同的中文分詞演算法,可謂百花齊放.但現在似乎還沒有針對未登陸詞的識別演算法,有鑑於此,我特地寫了乙個,拋磚引玉.演算法的假設 1.未登陸詞是由單字組成的 2.如果乙個字同時屬於2...
一種快速的未登陸詞識別方法 原理和實現
一種快速的未登陸詞識別方法 原理和實現 最近網路上關於分詞的演算法已經很多了,在實際應用中每個人根據對分詞的不同理解寫了不同的中文分詞演算法,可謂百花齊放.但現在似乎還沒有針對未登陸詞的識別演算法,有鑑於此,我特地寫了乙個,拋磚引玉.演算法的假設 1.未登陸詞是由單字組成的 2.如果乙個字同時屬於2...
一種基於有序序列mapjoin的方法
在解決資料傾斜問題時,我們經常會採用一種方式 mapjoin,按照hive的實現,mapjoin是將其中一張表在map的過程中載入到記憶體中,但是如果在join的表中,最小的表的資料量也不小的情況下。我們該怎麼辦呢?其中一種解決的方式是 將兩張表需要實現排序 直接用hadoop解決 如下,兩張表都是...