作為一個英語學習愛好者,我發現我們學了那么多年英語,雖然現在看英語文章已經不怎么吃力,但是如果要自己寫一篇英語文章,就總是感覺單詞雖然都懂,可要拼出一句有水平的句子就很難。其原因我覺得是我們平時雖然做了不少的閱讀,但只是在被動地將英語信息轉化成大概的中文意思理解,而沒有試着反過來訓練一下從中文怎么表達成英文。作為一個程序員有一個好處就是,當你發現一個需求的時候可以自己試着做個東西來玩玩,為了做這個學習工具,我首先想到了有些新聞網站會提供雙語新聞(比如酷優網http://www.cuyoo.com/home/portal.php),然后我的思路就簡單成型了,先搞個網絡爬蟲,把一些雙語新聞網頁抓取下來,然后將每一句中英文對照抽取出來,再做個圖形界面,每次先顯示一條中文,讓用戶嘗試輸入英文翻譯,寫不出來可以查看原英文提示,再提供一個筆記功能用於記錄一下特殊詞匯,表達方式和體會等,下面就給大家看看我是如何一一實現這些功能的。
1 網頁抓取框架—scrapy
所謂的網絡爬蟲,其實就像我們使用的瀏覽器,它去訪問一個個鏈接,然后把對應的網頁下載下來,所不同的是瀏覽器把文件下載下來后就呈現出來一個頁面,而爬蟲則可以根據我們定義的規則去自動地訪問網站里的鏈接,然后把下載到的網頁文件進行處理,並抽取出我們所要的數據。如果要自己實現一個網絡爬蟲,就要寫一個模擬http客戶端,還要實現文本解析等功能,還是挺麻煩的,這時候可以找找有什么好用的開源軟件。Scrapy(http://scrapy.org/)就是一個很不錯的工具,它是一個使用python實現快速高級的網頁抓取框架,使用它的時候,你只需要簡單地定義你要抓取的網頁url,還有對每個抓取到的頁面需要進行的處理操作,其它的都可以由scrapy完成,有興趣的朋友可以看看它提供的教程(http://doc.scrapy.org/en/0.18/intro/tutorial.html),現在開始我們的工作。
(1)在安裝scrapy后,在shell終端下隨便找個目錄運行命令:
scrapy startproject bilingual (自己取的項目名)
得到如下面所示的一個項目結構
bilingual/ scrapy.cfg bilingual/ __init__.py items.py pipelines.py settings.py spiders/ __init__.py ...
scrapy提供這些文件讓我們自定義對抓取到的數據的處理過程,其中spiders目錄下用於存放用戶定義的spider類,scrapy根據這里所定義的類進行信息抓取,在spider類中,需要定義初始的url列表,以及根據什么規則爬取新的鏈接和如何解析抽取下載到的網頁信息,我這里為了簡單,就只在spiders目錄下寫了一個spider進行處理,沒有使用其它功能。
(2)在spiders目錄下,創建文件cuyoo.py (自定義的spider名,也就是要抓取的網站名),代碼如下
1 from scrapy.selector import HtmlXPathSelector 2 from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor 3 from scrapy.contrib.spiders import CrawlSpider, Rule 4 5 import codecs 6 import os 7 8 class CuyooSpider(CrawlSpider): 9 name = 'cuyoo' 10 allowed_domains = ['cuyoo.com'] 11 start_urls = [ 12 'http://www.cuyoo.com/home/portal.php?mod=list&catid=2'] 13 14 rules = ( 15 Rule(SgmlLinkExtractor(allow=r'.*mod=view_both.*'), callback=‘parse_item',
follow=False), 16 ) 17 18 def __init__(self, *arg, **kwargs): 19 super(CuyooSpider, self).__init__(*arg, **kwargs) 20 self.output = codecs.open("data", "wb", "utf-8") 21 22 def __del__(self): 23 self.output.close() 24 25 def parse_item(self, response): 26 hxs = HtmlXPathSelector(response) 27 title = hxs.select("//h4[@class='ph']/text()").extract() 28 english = hxs.select('//div[@id="en"]/text()').extract() 29 chinese = hxs.select('//div[@id="cn"]/text()').extract() 30 self.output.write("---" + title[0].strip() + "---") 31 self.output.write(os.linesep) 32 for i in range(len(english)): 33 self.output.write(chinese[i].strip()) 34 self.output.write("->") 35 self.output.write(english[i].strip()) 36 self.output.write(os.linesep)
稍微解釋一下,在上面這個spider中,我在star_urls成員中放了一個鏈接,http://www.cuyoo.com/home/portal.php?mod=list&catid=2,打開這個鏈接可以看到下面這個網頁:
可以看到,在這個網頁中有多個新聞鏈接,每個鏈接點擊雙語對照可以得到中英文對照版的新聞,查看源代碼可以看出其鏈接形式為:portal.php?mod=view_both&aid=19076,所以在rules里定義規則
Rule(SgmlLinkExtractor(allow=r'.*mod=view_both.*'), callback=‘parse_item',follow=False)
用正則表達式表示包含'mod=view_both’的鏈接,scrapy在訪問該網頁時,就會自動抓取符合所定義的規則的所有鏈接,這樣就將這一頁里的所有中英文對照的新聞都抓取了下來,然后對每個抓取到的網頁調用parse_item(self, response)進行處理
(3) 因為我們要的只是網頁里的中英文新聞內容,所以要對下載到的網頁進行信息抽取,scrapy提供了XPath查找功能,讓我們可以方便地抽取文檔節點內容,不了解XPath可以看看W3C的教程(http://www.w3school.com.cn/xpath/),要抽取信息,首先還是要分析該新聞網頁的結構,可以使用scrapy提供的命令行工具來分析網頁結構和試驗xpath語句,首先運行命令
scrapy shell 'http://www.cuyoo.com/home/portal.php?mod=view_both&aid=19076'
將網頁下載下來后,再輸入view(response),可在瀏覽器查看下載到的網頁
可以看出,新聞的兩種格式分別包含在兩個div中,一個id為en,另一個為cn,所在在parse_item()中,分別使用
hxs.select('//div[@id="en"]/text()').extract() 和 hxs.select('//div[@id="cn"]/text()').extract()
將內容抽取出來,並按格式寫到文件中。
(4)在項目目錄下運行 scrapy crawl cuyoo 開始抓取,最終得到如下圖所示意的文件
2 圖形界面
有了抓取到的數據,接下來要怎么做就可以自由發揮了,我的圖形界面是通過Qt實現的,個人覺得很方便好用,這一塊沒什么好說的,就直接給大家看看成果吧。
程序界面
選擇文章
查看提示
最后還有一個記筆記的功能還沒實現,本來是想通過使用印象筆記的SDK,把筆記直接記到印象筆記上的,但是因為他們的SDK的C++版沒有教程文檔,而且好像帳號也有點復雜,還是等以后再找時間實現吧。
3 總結
做這個東西收獲了兩點,第一是讓我感到編程其實很有用,不僅限於工作和學習,只要有想法,我們能做的東西很多。第二是關於開源軟件,現在的開源軟件很多,使用開源的東西很方便,也很有趣,同時在使用的過程中我們也可以參與到其中,比如我在用scrapy的時候,在上面提到的這樣一個命令
scrapy shell 'http://www.cuyoo.com/home/portal.php?mod=view_both&aid=19076'
一開始我的鏈接沒用引號括起來,因為&在shell里是個特殊符號,表示后台運行,所以鏈接里的第二個參數在運行的時候就沒了,后來想明白后,問題解決了,我覺得這個問題別人可能也會遇到,所以就在scrapy的github頁面上給提了這個問題,希望他們能加到tutorial文檔里,然后過了一兩天,他們就真的加上了,這讓我感到很高興,也很佩服。
好了,寫得好長,謝謝觀看~