[转载]用网络爬虫给自己写个英语学习工具 – Benjamin-T – 博客园.
作为一个英语学习爱好者,我发现我们学了那么多年英语,虽然现在看英语文章已经不怎么吃力,但是如果要自己写一篇英语文章,就总是感觉单词虽然都 懂,可要拼出一句有水平的句子就很难。其原因我觉得是我们平时虽然做了不少的阅读,但只是在被动地将英语信息转化成大概的中文意思理解,而没有试着反过来 训练一下从中文怎么表达成英文。作为一个程序员有一个好处就是,当你发现一个需求的时候可以自己试着做个东西来玩玩,为了做这个学习工具,我首先想到了有 些新闻网站会提供双语新闻(比如酷优网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文档里,然后过了一两天,他们就真的加上了,这让我感到很高兴,也很佩服。
好了,写得好长,谢谢观看~