這兩天寫一個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