记录Request + BeautifulSoup爬取中国现代诗歌大全网站上的4000+现代诗的过程
原文在我的博客:Anywheredoor也可以找到
歡迎來玩呀!
最近想做一個和現代詩有關的小項目,第一步就是要考慮數據的問題。經過搜索,發現網上已經有大神開源了現代詩數據庫。但是我沒有借用,還是選擇自己去爬。主要是由于,難得有想做的東西,自己從頭做才能學到東西。更何況親手爬的數據才可以為所欲為。
在做這件事情之前,我在中國大學MOOC聽了北京理工大學嵩天老師的課程。也順便學了下Python。所以這次也算是學習過后給自己交的作業。
然后一個派桑菜就這樣出發了。
第一步 明確需要的數據
我的需求很簡單,就是想要詩人姓名,詩歌標題,詩歌內容。也不需要id什么的,所以設想的數據格式就是這樣的:
[ {poetName:poemTitle:poemText:[“第一句”,”第二句”….] }, {……. }, …. ]第二步 尋找合適的目標網站
網站介紹:
我找到的網站是:
中國現代詩歌大全
這個網站收藏有500多位詩人的5174首現當代詩。并且是一個公益站點,網站內容只要是非營利非商業就可以任意轉載,無需授權。雖然網站曾經應該是提供過源碼或者數據庫的下載(因為有這個link),但是現在已經是404了。這正好讓爬蟲有了用武之地。
網站url
網站中對詩歌的展示是采用每位詩人一個網頁的形式。而且網頁的url用詩人姓名的拼音命名,如詩人阿斐的url就是:
http://www.shigeku.com/xlib/xd/sgdq/afei.htm
再比如林徽因的url就是:
http://www.shigeku.com/xlib/xd/sgdq/linhuiyin.htm
這就幫了大忙了,這樣就可以只是通過拼接url地址去遍歷網頁。
只要暴力從首頁復制所有詩人的姓名,隨便用什么工具一鍵轉換成拼音,
再用word里的查找替換把分割的逗號左右兩端加上雙引號。
這樣就擁有了一個供拼接url使用的數組。
但是這樣做也會有漏洞,就是有時候轉換拼音的工具轉換出來的,并不一定就是實際url中使用的。如遇見“柏”這種字,工具會轉換成bai,而實際url中使用的是bo。
不過這個也好解決,后面我就單獨寫了個程序,實際遍歷一下訪問一下url,遇見報錯就手動改掉就可以了。畢竟工作量也不大,也就改了幾個人的拼音。
詩歌頁面分析
詩歌的展示是這樣的:
可以檢查一下源碼:
這個網站的布局非常簡單,我發現重要標簽(詩名、詩人名字)的align屬性都是center。這樣就可以通過指定這個特征篩選出需要的p標簽。
而具體每一句詩歌內容,則可以通過br標簽去定位。
第三步 編寫代碼
寫了兩個函數,第一個獲取text文本屬于通用的框架了,第二個是解析爬來的網頁內容,詳細的獲取自己需要的信息。代碼注釋很詳細所以直接貼:
# =======函數功能:用request庫獲取目標頁面的text文本 def getHTMLText(url):try:kv = {'user-agent':'Mozilla/5.0'} r = requests.get(url, timeout=30) r.raise_for_status() # 如果返回值不是200觸發HTTP異常r.encoding = r.apparent_encoding # 改變爬取的網頁編碼,使得print結果不是亂碼return r.text # 獲取網頁的所有信息except:return "Error!"# =======函數功能:解析并將爬來的網頁文本內容儲存成json # 要獲得指定網頁中作者,詩名,詩的內容 def fillPoemList(htmlTxt):soup = BeautifulSoup(htmlTxt, "html.parser")poemResult = [] #用來儲存本網頁爬取結果的數組poemList = soup.find_all('p',align="center")#獲取作者(正則表達式把開頭的詩選剔除掉)poetName = re.sub(r'詩選', "", poemList[0].text)#獲取每首詩的內容并存進數組a = 1 #list中的第0個元素是網頁標題詩人介紹,并不需要所以從1開始while(a < len(poemList)):nowPoem = poemList[a]poemContent = [] #用來裝每首詩的內容#每首詩的標題poemTitle = re.sub(r'\s',"",nowPoem.text)#剔除多余的空白字符#每首詩下面的詩歌內容,需要循環按句子存,以br標簽后面的內容為一句話for sentencesTag in nowPoem.next_sibling.next_element.find_all('br'):sentence = sentencesTag.next_siblingif sentence is None:passelse: poemContent.append(re.sub(r'\s',"",sentence)) #剔除多余的空白字符poemResult.append({'poetName': poetName, 'poemTitle': poemTitle, 'poemContent': poemContent})a += 1return poemResult一開始犯了個小錯誤,在獲取每一句詩的時候,用了br標簽的previous_sibling.就會導致每首詩都少爬了最后一句。我竟然都沒發現,有的現代詩真是太抽象了啊!少一句真的都發現不了。后來改成next就好了。
第四步 測試代碼
雖然寫好了程序,但是不想中途各種卡死處理報錯。所以還是要先測試一下。包括上文提到的排查錯誤的url,以及一些不適用于已定義函數規則的網頁。
我測試的時候直接把爬取內容print出來看,總之最后曬出來大概五六個人吧,沒辦法按照已經寫好的網頁去爬。要么就是網頁標簽搞特殊,要么就是原網頁本來就是亂碼。本來就是亂碼的頁面就沒辦法了,直接T出url名單,那些標簽搞特殊的人,可以踢掉之后把他們的名字記錄好,后面可以手動再為他們定制爬蟲規則等等。
第五步 正式運行爬蟲程序
然后寫個main函數,再寫兩行輸出成json的代碼就可以了。
build一下等幾分鐘就爬好了。文件夾中出現了10個json文件。
最后逐一打開json文件,prettify一下代碼。拖動滾動條大概瀏覽一下有沒有嚴重的亂碼。這一塊我做的不太好,寫代碼的時候沒有注意到一些細節:
有一些詩歌末尾會有一兩個亂碼。只要刪掉就行的那種。應該在寫代碼的時候就把它們篩除掉。但是我是最后才發現,也懶得再爬一次。就人工逐一瀏覽一下這10個文件,看到的就手動刪掉了。邊聽歌邊刪,還能順便讀讀詩,也蠻開心的。
還有一些詩人喜歡寫組詩,組詩的標題會有一個單獨的p標簽,也會被我的程序識別為一個詩歌,這樣的話存下來在json中就是一個空白對象。遇到這種也手動刪除。
有的詩歌名稱下面還有詩歌的簡短的介紹,也會被我的程序識別為標題。就會導致存進去的標題很長,這個不符合我后面項目的需求,只能手動刪。
還好在prettify之后,亂碼、空白、過長的標題都是相對來說比較容易看到的。只是一些人工的問題了。大概半個小時搞定。
第六步 結束
然后load一下這10個json文件,計算一下最終爬了來了多少詩。發現是4286首。
四千首已經足夠滿足我做項目的需求啦。
開心!
歡迎交流!歡迎指出我寫的不好的地方!歡迎夸我!
總結
以上是生活随笔為你收集整理的记录Request + BeautifulSoup爬取中国现代诗歌大全网站上的4000+现代诗的过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CSI笔记【9】:阵列信号处理及MATL
- 下一篇: 服务器硬盘型号详解