马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
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并获取页面并返回。
接下来,我们来分析一下返回得到的网页页面特征,看看怎么才能提取翻译的得到的结果。首先查看网页的源码,翻到如下图所示的位置:
可以发现结果标题处有一个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()方法不会对英文字符和数字一起其他一些字符进行转码,可以参考一下下面这段程序:
献上第二个函数,获取单词的所有意思: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
|