使用 flickr API 上传并获取外链
这两天写一个python的自动从word读取并向OJ的DIY添加题目的脚本,其中一个最痛苦的地方莫过于图片添加了。没被墙并且以前用过的图床只有flickr,第一次用API的方式写代码,一切都从零开始...
使用flickr API首先要向flickr申请一个应用程序,flickr会提供一个API_KEY和密码API_SECRET
之后去下载了python相关的第三方API,试了 Beej's Python Flickr API 和 flickr.py,两个API都挺郁闷,我需要的只有上传图片和获得图片外链两个功能,而两个都不能直接实现。Beej比较正式一点,是python官方指定的,没有直接获取外链的方法,而且代码又过于抽象,改不出来; flickr.py 代码相对简单很多, 但是没有图片上传方法。于是乎,自己动手,丰衣足食,把flickr.py的1k+行的源码删的剩200行,然后把Beej的代码中的上传部分挪了过来,搞了一整天,终于搞定了 T_T
官方API的大概原理很简单,就是向指定的网页get或者post一些值,然后服务器会返回一个XML结构的数据包,数据包中包含我们需要的信息。
首先要做的要进行身份认证并获取权限,我做的是一个非网页应用,认证需要三步:
第一步要获取一个Frob值,官方API中写的很清楚,方法(method)为"flickr.auth.getFrob",于是得到get的网址:
http://flickr.com/services/rest/?api_key=[api_key]&method=flickr.auth.getFrob&api_sig=[api_sig]
[api_key]就是你申请的api_key,而对于任何一次get或者post,都还要有一个api_sig的值,这个api_sig值是对之前参数的一个验证,他的计算方法是你的密码API_SECRET+所有参数按字典序排序之后的连接得到的字符串,然后进行md5hash之后的值,举例比如说上面的处理后的字符串就是:
[API_SECRET]api_key[API_KEY]methodflickr.auth.getFrob
取md5值就得到了api_sig
之后会返回一个xml格式文档:
<?xml version="1.0" encoding="utf-8" ?> <rsp stat="ok"> <frob>72157629793683591-1120f17051e65424-60155050</frob>
</rsp>
stat是"ok"也就表示请求有效,否则的话就表示请求出错,并会得到一个错误信息,如:
<?xml version="1.0" encoding="utf-8" ?> <rsp stat="fail"> <err code="97" msg="Missing signature" /> </rsp>
获取frob之后就进行第二步认证:
调用浏览器打开认证页面:
http://flickr.com/servers/auth/?api_key=[api_key]&perms=write&frob=[frob]&api_sig=[api_sig] api_sig=md5([api_secret]api_key[api_key]frob[frob]permswrite)
perms=write也就是说需要上传的权限,如果是read则是只读权限。用户登录并认证之后就可以进行第三步认证了:
第三步就是getToken,method='flickr.auth.getToken'
http://flickr.com/services/rest/?api_key=[api_key]&frob=[frob]&method=[method]&api_sig=[api_sig] api_sig=md5([api_secret]api_key[api_key]frob[frob]method[method])
然后返回得到Token值,最好把Token值保存到一个文件里面,以后每次操作都需要这个Token值,到这里就认证成功了。
认证成功之后就可以进行各项操作了,详细看官方的API方法:http://www.flickr.com/services/api/
上传图片的方法和其他方法是不同的,具体看这里http://www.flickr.com/services/api/upload.api.html,图片一般很大,只能用POST方法发送,而且官网有说:'photo'参数不应该包含在签名中。生成签名时,应包含所有其他 POST 参数。所以得到api_sig时只需包含api_key和auth_token两个参数。
这个在上传时花了好长时间,用各种方法上传都返回API_KEY无效的错误,所以只好拖出了Beej的代码,这才知道,这种大文件的传送必须不能和小的字符串相同,而是使用multipart的形式进行发送,网上查了一下multipart的的结构:
multipart的post信息各部分之间需要用 "--" + boundary 的形式隔开,boundary是随机生成的一个字串
然后是数据描述,接着就是数据了。为了跨平台,换行符是'\r\n'。还要注意,最后是 '--' + boundary + '--'。
另外,在申请头中要添加发送类型和boundary,如下的一段:
Content-Type:multipart/form-data; boundary=ttP6n0b1QZUBJp6bK6gbNw
这样就能够发送成功了,返回的信息中包含有图片的id号,根据id号,执行getInfo的方法(flickr.photos.getInfo),可以得到类似如下的信息:
<?xml version="1.0" encoding="utf-8" ?> <rsp stat="ok"> <photo id="7008341001" secret="d20e29fbed" server="7191" farm="8" dateuploaded="1332508355" isfavorite="0" license="0" safety_level="0" rotation="0" views="0" media="photo"> <owner nsid="60187189@N04" username="Amb.Flickr" realname="amb W" location="" iconserver="6204" iconfarm="7" /> <title>pic</title> <description /> <visibility ispublic="1" isfriend="0" isfamily="0" /> <dates posted="1332508355" taken="2012-03-23 21:12:35" takengranularity="0" lastupdate="1332509039" /> <permissions permcomment="3" permaddmeta="2" /> <editability cancomment="1" canaddmeta="1" /> <publiceditability cancomment="1" canaddmeta="0" /> <usage candownload="1" canblog="1" canprint="1" canshare="0" /> <comments>0</comments> <notes /> <people haspeople="0" /> <tags /> <urls> <url type="photopage">http://www.flickr.com/photos/ambition0109/7008341001/</url> </urls> </photo> </rsp>
得到其中包含的secret,server,farm值就可以构造一个外链了,构造方法看这里http://www.flickr.com/services/api/misc.urls.html
如上的大图外链就是 http://farm8.staticflickr.com/7191/7008341001_d20e29fbed_b.jpg 了
这样,flickr的部分就搞定了~~~
原文地址: http://www.cnblogs.com/ambition/archive/2012/04/11/2442802.html