鱼C论坛

 找回密码
 立即注册
查看: 3943|回复: 4

[技术交流] 网络爬虫之我的百度词典-解决Python中urlopen()中url不能包含中文的问题~

[复制链接]
发表于 2015-2-2 21:10:45 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
       看完了小甲鱼老师的python视频教程,感觉收获良多,于是开始尝试着写一写自己的东西。小编的这个网络爬虫程序叫做我的百度词典,其实使用爬虫技术对百度词典进行爬取。在编写这个爬虫的过程中,小编遇到了很多困难,有些是小甲鱼老师没有提到过的。不过这也正常,问题那么多,小甲鱼老师也不可能面面俱到,很多问题还是要自己解决。比起小甲鱼老师在上课时给我们演示的抓取有道词典的例子,我的这个抓取更具有通用性,因为很多网站都不像有道词典那样直接使用post并返回结果,大多数还是直接用网页呈现。另外很多post方式防御都很严,像百度在线翻译使用的post,我试了好多种方式都得不到response。
       废话不多说,现在进入正题。大家可以访问以下百度词典网站: http://dict.baidu.com/,输入单词之后会发现网址变了,而且规律很明显,所以url我们很容易就能推出url的组织方式,url组织方式为http://dict.baidu.com/s?wd=单词, 所以在编写爬虫的时候,单词替换为我们输入的单词即可。
首先导入需要的包:
  1. #encoding: utf-8
  2. #我的百度词典
  3. #Jack Jones
  4. #2015-2-2

  5. import urllib.request as ur
  6. import urllib.parse as up
  7. import re
复制代码

接下来写我们的第一个函数,openUrl(url):
  1. def openUrl(url='http://dict.baidu.com/s?wd=apple'):
  2.         request = ur.Request(url)
  3.         #print(url)
  4.         request.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0')
  5.         response = ur.urlopen(request)
  6.         html = response.read()
  7.         return html
复制代码
      上面这个函数用于打开url并获取页面并返回。
       接下来,我们来分析一下返回得到的网页页面特征,看看怎么才能提取翻译的得到的结果。首先查看网页的源码,翻到如下图所示的位置: 3_area.png
可以发现结果标题处有一个li标签,叫做<li rel="[url=]en-simple-means[/url]">简明释义</li>,所以我们待会写的代码,首先就要定位到这个地方来。然后可以发现,单词的词性(如名词、形容词)被strong标签包围着,可以发现<strong>n.</strong>,单词的意思被span标签包围,如<span>苹果;苹果树;苹果公司</span>,另外最后的<script>标签我们可以当做结束标志,所以接下来应该提取所有的strong标签和span标签,直到遇script标签结束提取。提取完了之后得到的字符串中,包含了单词的所有释义和词性,然后对这个字符串再进行提取即可(把那些html标签用re的sub方法去掉即可)。
       大家多试几组单词会发现,不同的单词,显示出来的结果不同(废话= =),但是没想到页面的布局也不一样(:funk:)。所以我们的正则表达式pattern要容纳各种情况,或者针对各种情况编写不同的正则表达式。
       另外,百度词典与其他词典一样,可以进行中英互译,大家在浏览器里面输入中文然后点击翻译,会发现网址上也会出现同样的格式,并且显示中文。可以如果把中文直接写入到urllib.request.urlopen()函数中会出现错误,因为这个函数里面的url只可以出现ascii字符。解决方法其实很简单,使用urllib.parse.quote()方法,对中文进行quote,这样返回的字符串浏览器会识别出来并且自动转换成中文,不信大家可以把这个地址(http://dict.baidu.com/s?wd=%E8%8B%B9%E6%9E%9C)复制到浏览器地址栏中回车一下,wd=后面的字符会自动变为"苹果"二字,后面那个一大堆%开头的字符串其实是"苹果"quote之后的字符串。提醒一下: quote()方法不会对英文字符和数字一起其他一些字符进行转码,可以参考一下下面这段程序:
4_quote.png
献上第二个函数,获取单词的所有意思:
  1. def getMeaning(word):
  2.         #根据单词生成url
  3.         url = 'http://dict.baidu.com/s?wd=' + up.quote(word.replace(' ', '+')) #使用quote将中文转码
  4.         url = url.replace('%2B', '+')
  5.         html = openUrl(url).decode('utf-8')
  6.         #确定单词释义区域
  7.         pattern = re.compile(r'<li rel="en-simple-means">简明释义</li>.+?<script>', re.DOTALL)
  8.         area = pattern.search(html)
  9.         if area == None:
  10.                 return []
  11.         area = area.group()
  12.         #print(area)
  13.         #标志是否算出多余的结果
  14.         deleteMore = False
  15.         #提取单词所有释义
  16.         pattern = re.compile(r'<strong>.+?(</span>|</a>)', re.DOTALL)
  17.         if pattern.search(area):
  18.                 iterator = pattern.finditer(area)
  19.         else:
  20.                 pattern = re.compile(r'<a.+?</a>', re.DOTALL)
  21.                 iterator = pattern.finditer(area)
  22.             deleteMore = True

  23.         #分解每个释义,存入列表中
  24.         meanings = []
  25.         pattern = re.compile('(<.+?>)|(&.*?;)', re.DOTALL)
  26.         engPattern = '[a-zA-Z ]'
  27.         for meaning in iterator:
  28.             meaning = meaning.group()
  29.             #print(meaning)
  30.             #print(pattern.sub('', meaning))
  31.             meaning = pattern.sub('', meaning)
  32.             if deleteMore and re.search(engPattern, meaning) == None:
  33.          break
  34.             meanings.append(meaning)

  35.         return meanings
复制代码
然后写上主函数就可以了:
  1. def main():
  2.         word = input('请输入单词: ')
  3.         meanings = getMeaning(word)
  4.         if len(meanings) != 0:
  5.                 print('释义:')
  6.                 for meaning in meanings:
  7.                     print(meaning)
  8.         else:
  9.                 print('没有释义!')


  10. if __name__ == '__main__':
  11.     main()
复制代码
      考虑到排版的问题,不知道这些代码直接复制下来排版会不会正常。为了给大家提供方便,小编把自己写的py源文件上传,大家可以直接下载。
       源代码地址: http://pan.baidu.com/s/1qWr201Y


地址

地址
2_viewSource.png

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-2-2 22:34:42 | 显示全部楼层
看不懂啊。。。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-2-2 23:29:45 | 显示全部楼层
Angel丶L 发表于 2015-2-2 22:34
看不懂啊。。。。

写的不是太详细= =其实就是分析html页面的特点,然后用正则提取
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-2-3 16:31:42 | 显示全部楼层
谢谢楼主!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-2-3 16:44:44 | 显示全部楼层
支持楼主。。。虽然我看的不咋懂。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-23 16:19

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表