人生苦短,我用Python。
Why every programmer should learn Python or Ruby
更新记录:
--2015.10.12--
第一段代码错误更正,感谢@Aldrin的提醒~~
req = urllib.request.urlopen('http://placekitten.com/g/500/600')
在改代码的时候上面这一段中的urlopen是应该改为Request的。
--2015.10.12--
使用代理
简单地图片下载爬虫
废话不多说,来看第一个例程。
import urllib.request
req = urllib.request.Request('http://placekitten.com/g/500/600')
response = urllib.request.urlopen(req)
cat_img = response.read()
with open('cat_500_600.jpg','wb') as f:
f.write(cat_img)
这是最初级的一个实例,上面这个爬虫从这个猫奴网站下载了一可爱的小猫。这算是最简单的一个python爬虫了,只用到了一个urlopen方法。
通过上面的例程搞懂以下几个问题:
- urllib模块有什么作用
- urlopen函数的使用
- 文件的open操作
- with语句的用法
查阅一番资料和Python的API文档,可以得到以下答案:
urllib模块是Python的一个获取url(Uniform Resource Locators,统一资源定址器)的模块。
urlopen函数提供了一个非常简洁的接口,使得Python用各种各样的协议获取url。对请求的url返回一个response对象。这个response是一个file-like的对象,能用.read()函数操作这个response对象。
fp = open("文件名",打开模式)直接打开一个文件,如果文件不存在则创建文件
- with 语句是从 Python 2.5 开始引入的一种与异常处理相关的功能,从 2.6 版本开始缺省可用(参考 What's new in Python 2.6? 中 with 语句相关部分介绍)。with 语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭、线程中锁的自动获取和释放等。——源自《浅谈 Python 的 with 语句》
通过爬虫实现在线翻译
在有了以上基础以后,开始摸索更为复杂的爬虫。第二个例程要实现通过爬虫使用有道词典的在线翻译。
还是先上源码:
#coding: utf-8
import urllib.request
import urllib.parse
import json
content = input("what do you want to translate?")
url = 'http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule&smartresult=ugc&sessionFrom=null'
data = {}
data['type'] = 'AUTO'
data['i'] = content
data['doctype'] = 'json'
data['xmlVersion'] = '1.8'
data['keyfrom'] = 'fanyi.web'
data['ue'] = 'UTF-8'
data['action'] = 'FY_BY_CLICKBUTTON'
data['typoResult'] = 'true'
data = urllib.parse.urlencode(data).encode('utf-8')
response = urllib.request.urlopen(url, data)
html = response.read().decode('utf-8')
json.loads(html)
target = json.loads(html)
print("result:%s"% (target['translateResult'][0][0]['tgt']))
比第一个复杂了好多。不着急,一行一行看。
相比于第一个例程里只有urllib.request
模块,这次我们多导入了两个模块urllib.parse
和json
。先不管这些,让我们先来分析一下如何实现使用有道词典的在线翻译。
打开Chrome进入有道翻译的页面,我们先简单看一下翻译“i love you”时,浏览器与服务器之间的交互,顺便了解我们的代码。
进入“审查元素”页面,我们在输入完“i love you”之后点击翻译,看到“Network”下一大堆浏览器与服务器之间的交互。
我们点击进入第一个浏览器向服务器提交的POST请求,来分析下想要用代码模拟人的操作,需要些什么。
如上图所示,我们要代码实现交互,就要模拟浏览器,向服务器提交POST。那么如何完成呢,就要接住urlopen这个函数了。查看API文档,我们找到urlopen这个函数,看看他到底是如何使用的:
urlopen函数在定义时可以传两个参数分别为url和data。url为我们实际需要访问的链接,这里要特别注意,url参数的值必须为图三中的Request URL梭织链接,而并非浏览器地址栏中的url。而data参数为字典类型,内容就是我们要向服务器提交的POST内容,也就是图四中From Data的内容了,于是我们在代码(第6~16行)中直接定义即可。
这里还有一点需要注意,在代码的第18行,有关字符编码。我们的POST要以字符串编码的形式提交,而我们定义的却是字典类型的数据,这时候就要借助urllib.parse模块中的urlencode()
函数来实现转义。格式为“utf-8”(.encode('utf-8'))。
好了。在爬取网页之前的准备工作就已经全部完成了,接下来我们进行爬取并打印response对象的内容:
没有错,我们获得了json格式的内容,那什么是json,json模块中有哪些函数,它们又如何使用?
接下来就是从json数据中提取出我们想要的内容了。使用json.loads()
提取出字典后,打印就好了。
最后来测试下整体的效果:
使用代理
当我们用python爬虫进行一些比较密集的爬取(比如下载某网站的所有图片啊)时,服务器会对我们进行封锁,那么我们要如何继续疯狂的爬啊爬呢?
没有错,就是使用代理。我们用很多个不同的ip地址去登陆服务器,这样服务器就会误认为是很多个不同的人在链接,所以就不会封锁你咯。再搭配上面提到的对Headers的设置,我们就可以快速的进行爬取了。
在Python中使用代理一共有如下几步:
- 设置一个字典作为参数,要这样的格式:{‘类型’:‘代理ip:端口号’}
- 调用urllib.request.ProxyHandler()方法,传入我们刚刚设置的字典参数
- 定制、创建我们的opener,用来获取url
- 安装我们“私人定制”的opener
- 调用opener
呐,知道了这些,我们就来实践一下,使用代理来访问一个宝岛台湾的网站whatismyip,这是一个很有意思的玩意儿,这个网站只有一个作用那就是显示你当前访问它使用的IP地址。
好,先来看看代码:
#coding: utf-8
import urllib.request
import urllib.parse
import random
url = 'http://www.whatismyip.com.tw'
iplist = ['222.88.236.236:843','125.131.193.43:80','183.252.18.131:8080']
proxy_support = urllib.request.ProxyHandler({'http':random.choice(iplist)})
opener = urllib.request.build_opener(proxy_support)
opener.addheaders = [('User-Agent','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36')]
urllib.request.install_opener(opener)
response = urllib.request.urlopen(url)
html = response.read().decode('utf-8')
print(html)
我们还是一句一句的来分析,首先是我们要访问的域名,不多说。往下走,我们新建一个列表,来储存待用的ip地址。至于代理ip的话,网上有好多,百度一下,copy过来。
接下来我们定义了一个proxy_support,后面用的是urllib.request.ProxyHandler()方法,从这一句开始,我们开始使用代理。然后我们自定义了一个opener,并且安装了它
还是从文档开始看起:
功能就是大概我们描述的样子。接下来的的大家都已经熟悉了,最后我们打印获得的网页HTML源码,来看我们到底用了什么ip地址去访问:
再运行一次,看看,两次的访问ip可是不一样的咧。
需要注意的一点是,这些代理ip可是每天都在变得,如果如果你想运行参考例程,最好是重新搜一下代理ip并更新代码中的iplist。
(未完待续……)