鱼C论坛

 找回密码
 立即注册
查看: 4075|回复: 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=单词, 所以在编写爬虫的时候,单词替换为我们输入的单词即可。
首先导入需要的包:
#encoding: utf-8
#我的百度词典
#Jack Jones
#2015-2-2

import urllib.request as ur
import urllib.parse as up
import re
接下来写我们的第一个函数,openUrl(url):
def openUrl(url='http://dict.baidu.com/s?wd=apple'):
        request = ur.Request(url)
        #print(url)
        request.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0')
        response = ur.urlopen(request)
        html = response.read()
        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
献上第二个函数,获取单词的所有意思:
def getMeaning(word):
        #根据单词生成url
        url = 'http://dict.baidu.com/s?wd=' + up.quote(word.replace(' ', '+')) #使用quote将中文转码
        url = url.replace('%2B', '+')
        html = openUrl(url).decode('utf-8')
        #确定单词释义区域
        pattern = re.compile(r'<li rel="en-simple-means">简明释义</li>.+?<script>', re.DOTALL)
        area = pattern.search(html)
        if area == None:
                return []
        area = area.group()
        #print(area)
        #标志是否算出多余的结果
        deleteMore = False
        #提取单词所有释义
        pattern = re.compile(r'<strong>.+?(</span>|</a>)', re.DOTALL)
        if pattern.search(area):
                iterator = pattern.finditer(area)
        else:
                pattern = re.compile(r'<a.+?</a>', re.DOTALL)
                iterator = pattern.finditer(area)
            deleteMore = True

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

        return meanings
然后写上主函数就可以了:
def main():
        word = input('请输入单词: ')
        meanings = getMeaning(word)
        if len(meanings) != 0:
                print('释义:')
                for meaning in meanings:
                    print(meaning)
        else:
                print('没有释义!')


if __name__ == '__main__':
    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-11-22 13:58

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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