使用 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 

posted @ 2012-04-12 00:34  Amb@HDU  阅读(4787)  评论(0编辑  收藏  举报