最近需要抓取語料庫,在一個NLP的論壇上看到有人民日報的1946到2003的所有資料。準備把這些資料抓取下來(雖然有點老了,但是聊勝於無,哪位高人知道更好的來源請告知)。程序是用python寫的,主要用到bs4解析模塊。由於是新手沒有使用多線程,事實證明效率果然不快,因爲有大量的數據IO。等看完多線程爬蟲再實現一個多線程版本的。先將就用吧。
在windows下運行的同學,請把程序中文件夾和文件名的編碼格式改爲GBK,代碼如下:
#coding:utf-8
#author:zhangyang
#date:2015-5-17
#此程序用於爬取人民日報下的數據資源。主頁面需要提取包括1946年到2003年之間所有月份
#次級頁面是各個月份的所有報道
#末級頁面是報道內容
import urllib2,bs4,os,re
from time import clock
#關於bs4解析url的方法可以參看:http://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html
starturl="http://rmrbw.info/"
testMonthURL="http://rmrbw.info/thread.php?fid=6"
def getSoup(url):
pape=urllib2.urlopen(url)
soup=bs4.BeautifulSoup(''.join(pape),'lxml')
return soup
#從主頁面中讀取每一年中每個月的URL組成一個URLLIST返回,
def getDataFromMainURL():
urllist=[]
mainSoup=getSoup(starturl)
alist=mainSoup.find_all('a','fnamecolor')
for item in alist:
urllist.append(starturl+item['href'])
return urllist
#處理每一個月的首頁面,包括得到總的子頁面數和當前文檔URL
#並把所有子頁面返回的URLLIST組成總的URLLIST
#根據得到URL爲每一個月創建的一個文件夾。
def getDataFromMonth(monthURL):
filepath=os.getcwd()+os.path.sep+"data"+os.path.sep
urllist=[]
soup=getSoup(monthURL)
title=soup.find('a','fl') #找到年月的標籤位置
month=title.contents[0]
curpath=os.getcwd()
#print month.encode('utf8')
datapath=curpath+os.path.sep+"data"+os.path.sep+month.encode('utf8')
if os.path.exists(datapath)==False:
os.mkdir(datapath) #創建好當月文件夾
pages=soup.find('div','pages').contents[-1]
totalpage=pages.split(' ')[3].split('/')[1] #得到總頁面數
for num in range(int(totalpage)):
curURL=monthURL+"&page="+str(num)
urllist+=getDocementList(curURL)
print "已載入當前月份的所有urllist"
return datapath,urllist
#得到當前頁面的文檔URL組成URLLIST返回
def getDocementList(curURL):
urllist=[]
curSoup=getSoup(curURL)
res=curSoup.find_all(id=re.compile("a_ajax_"))
for item in res:
urllist.append(starturl+item['href'])
print "已載入當前頁面的所有文檔url"
return urllist
#得到docement中的內容並保存到文件中
def getDocement(docURL):
docSoup=getSoup(docURL)
title=docSoup.find('h1','fl').get_text()
title=title.strip().split(' ')[0]
cont_div=docSoup.find('div','tpc_content')
cont=cont_div.get_text().strip()
pattern=re.compile(r'<br/?>')
#for item in cont_div:
#print type(item)
#if not re.match(str(item)):
#cont+=str(item)
#if str(item)!='<br/>' or str(item)!='<br>':
#cont+=str(item)
return title,cont
#月份頁面下的控制程序,輸入爲月份的URL。並把爬取的內容分別存入到文件中
def monthMain(monthURL):
start=clock()
datapath,urllist=getDataFromMonth(monthURL)
for url in urllist:
try:
doc_title,doc_cont=getDocement(url)
#print doc_title
doc_title=doc_title.encode('utf8')
filename=datapath+os.path.sep+doc_title+".txt"
f=open(filename,'w')
except Exception as e:
print e
continue
doc_cont=doc_cont.encode('utf8')
f.write(doc_cont)
f.close()
end=clock()
print "finish input data to "+datapath
print "running time is "+str(end-start)+"s"
def main():
starttime=clock()
urllist=getDataFromMainURL()
for url in urllist:
try:
monthMain(url)
except Exception as e:
print e
continue
endtime=clock()
print "total running time is "+str(endtime-starttime)+"s"
if __name__=="__main__":
main()