[转载]用网络爬虫给自己写个英语学习工具 - Benjamin-T - 博客园

[转载]用网络爬虫给自己写个英语学习工具 – Benjamin-T – 博客园.

作为一个英语学习爱好者,我发现我们学了那么多年英语,虽然现在看英语文章已经不怎么吃力,但是如果要自己写一篇英语文章,就总是感觉单词虽然都 懂,可要拼出一句有水平的句子就很难。其原因我觉得是我们平时虽然做了不少的阅读,但只是在被动地将英语信息转化成大概的中文意思理解,而没有试着反过来 训练一下从中文怎么表达成英文。作为一个程序员有一个好处就是,当你发现一个需求的时候可以自己试着做个东西来玩玩,为了做这个学习工具,我首先想到了有 些新闻网站会提供双语新闻(比如酷优网http://www.cuyoo.com/home/portal.php), 然后我的思路就简单成型了,先搞个网络爬虫,把一些双语新闻网页抓取下来,然后将每一句中英文对照抽取出来,再做个图形界面,每次先显示一条中文,让用户 尝试输入英文翻译,写不出来可以查看原英文提示,再提供一个笔记功能用于记录一下特殊词汇,表达方式和体会等,下面就给大家看看我是如何一一实现这些功能 的。

网页抓取框架—scrapy

所谓的网络爬虫,其实就像我们使用的浏览器,它去访问一个个链接,然后把对应的网页下载下来,所不同的是浏览器把文件下载下来后就呈现出来一个页 面,而爬虫则可以根据我们定义的规则去自动地访问网站里的链接,然后把下载到的网页文件进行处理,并抽取出我们所要的数据。如果要自己实现一个网络爬虫, 就要写一个模拟http客户端,还要实现文本解析等功能,还是挺麻烦的,这时候可以找找有什么好用的开源软件。Scrapyhttp://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文档里,然后过了一两天,他们就真的加上了,这让我感到很高兴,也很佩服。

  好了,写得好长,谢谢观看~
赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏