栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

从零开始实现一个终端小词典

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

从零开始实现一个终端小词典

最近花了一点时间写了一个词典小工具。复制你需要查询的单词,在终端输入ss即可得到查询结果。查询过的单词和结果会被追加写入本地的文件,生成生词本。

 coderDic.gif

实际Mac上单词的查询非常的简单:你可以 command + control + d 来自动划词查询,也可以设置手势三指轻拍来唤出结果。我不满意的地方在于这种查询方式无法汇总我查询过的单词,另外翻译的结果很多时候我看起来太过冗余。

 mac自带词典的查询结果

另外一个我动手的原因是:之前的文章一直太过理论了,为了整理这些内容花了太多精力在概念的理解上,我希望能够找一个机会动手写一写代码。

项目地址:CoderDic
编程语言:python 2.7.10
系统环境:macOS 10.12.6
依赖库:参见requirements.txt


要实现这样一个小工具,第一步需要思考的是翻译来源。我本身是希望借助已有的翻译 api来做这件事情,比如百度翻译和有道翻译。可是查看文档以后我觉得不是特别满意,理由如下:

  • 需要自己去弄一个key

  • 这部分api应用场景是给出一个最贴切的翻译结果,所以查询结果单一不全面。

举一个简单的例子,我利用Postman向百度翻译请求翻译apple

{     "from": "en",     "to": "zh",     "trans_result": [         {             "src": "apple",             "dst": "苹果"         }     ] }

作为翻译api,这样的返回没有问题,按照用户查询的内容给出最可能的翻译;但是作为词典,这样的结果不太能够接受。所以我放弃了这种方案,选择了爬取百度搜索得到的结果。

比如我需要查询apple,我可以百度搜索apple 翻译

 apple 翻译

“单词” + 翻译 组合搜索的方式,返回的第一条就是百度翻译的结果,附带音标,多语义解释,例句和包括复数过去式等其他的解释。

这样第一步就明确了,我们模拟向百度发起一个搜索请求,获取返回结果,代码如下

def searchWord(word):     # get html text     request = urllib2.Request('http://www.baidu.com/s?wd='+urllib.quote(word + "翻译"))     response = urllib2.urlopen(request)     #parse html     soup = BeautifulSoup(response.read(), "lxml")

利用urllib2和BeautifulSoup来获取百度返回的结果并进行解析。借助Chrome的开发者工具,我们来分析一下返回界面,确定我们需要的翻译结果在哪里。

 Chrome 开发者工具

可以发现所有的结果都包含在一个class=op_dict_content的div里

content = soup.find_all("div", {'class':"op_dict_content"})     if content:             print 'get success'     else:             print ‘get fail! Please check your word is correct!'

我们尝试获取这个div,如果获取成功继续解析,失败则提示检查输入单词。重复上述步骤,我们逐个获取需要的内容。

        #get word symbol         symbol = ''         symbols_table = soup.find(class_="op_dict_table")         symbol_trs = symbols_table.find_all("tr")         for tr in symbol_trs:             for td in tr.find_all('td'):                 symbol += stringHandle(td.getText()) + ' '             print symbol         #get translations         translations = []         translation_table = soup.find_all(class_ = re.compile("op_dict3_english_result_table"));         for tr in translation_table:             aaa = ''             for td in tr.find_all('td'):                 temp = stringHandle(td.getText())                 if temp == '[其他]':                      temp = 'n' + temp + 'n'                 translations.append(temp);                 aaa += temp + ' '             print aaa         print 'n'

音标和翻译都成功获取,但是在拿例句的时候发生了一些问题,在返回的网页源码当中是没有这部分内容的。

原因非常简单,这部分的内容是通过Ajax动态获取的。要获得这部分的内容显然直接抓取不太现实,为了获取这部分动态的资源我们可以利用Selenium+PhantomJS来模拟浏览器的环境,从而请求获取这部分的内容。

但是,但是!这个框架太重了!我们只是要例句这么一点内容,不至于这么复杂。让我们分析一下网页到底请求了什么,简单模拟一下就可以了。

我查看了网页的源码,确实在一个