本文介紹 Twitter 的基礎結構,向 PHP 開發人員展示如何使用公共庫從他們自己的或朋友的時間線中提取狀態並將它轉換為其他格式,特別是 RSS。
在深入講解 Twitter 主題之前,我有一些話要說。儘管我現在是 Twitter 的忠實用戶和追隨者,但是在它最初出現時,我對它是有點迷惑的。事實上,我一直對它心懷敵意。
下面我給您介紹一下 Twitter 的背景
當 2007 年的 South by Southwest 大會引入了 Twitter 時,我的一位好朋友就打電話告訴了我,他說:“你應該去註冊一個帳戶,Twitter 真是太神奇了!” 顯然,在整個會議廳中,巨大的屏幕一直顯示著微型博客消息。那一年我一直在旅行,去過很多地方,但並沒有實際參加 South by Southwest 大會。確實,我太局限於自己的小世界了,沒有對它引起真正的重視。微型博客?Tweet?這些傢伙說的都是什麼啊?
不久之後,我有機會去嘗試這種服務,但發現它並不適合我。事實上,我認為 Twitter 非常浪費時間。我並沒有發現我的同伴們喜歡去追隨什麼,即使他們發明了曲速引擎(warp drive)或治癒了癌症。相反,當時的 Twitter 用戶似乎更多地討論剛剛為小孩做的火腿三明治這樣的話題。
很快過了幾個月之後,我突然發現自己一直在使用 Twitter。我使用它來查找新資源、關注總統候選人、聯繫遠方的朋友。為什麼會有如此大的轉變?我真的不知道。許多 Twitterzen 夥伴都能明白我這種感受,就像擁有您的第一部手機一樣。有一天您發現拿著一部昂貴的手機到處走是一件很愚蠢的事,因為到處都有公共電話亭、住宅電話和辦公電話,您可以方便使用。但是馬上發生了一件事,您被困在 East Outersticksvillestan 的公路邊,束手無策,您就會感謝這部小小的手機救了您的命。
不過有一件事是確定的:與手機取代公用電話不同,Twitter 並沒有取代我的社會網路活動 — 相反它起到了促進的作用。我經常使用 Twitter 發布我在 Web 上找到的有趣條目 — 使我的追隨者感到開心或引發思考的文檔和參考資料。希望它們至少在某一方面有用。確實如此,有一陣子我發現我總是在 Twitter 上面說 “該死的,我需要咖啡” 或 “昨天晚上很無聊” 之類的話,但是我盡量剋制自己說這些廢話。
從某種程度上說,作為一名開發人員,我需要的更多。我需要進行修改,將事情分類,或者至少指出工作原理。在上一篇文章中,我說明了如何用 PHP 構建一個簡單的微型博客工具,這種輕量級工具可以在 Intranet 應用程序或其他封閉系統的環境中良好地工作。
在本文中,我想對 Twitter 的內容進行更深入一點的介紹,簡單探討一下 API,然後轉向一個可以簡化某些任務的著名的公共 PHP 庫。本文的目標是說明工作原理,並提供一些工具,您可以利用這些工具將 Twitter 時間線導出到 RSS。目的是什麼呢?共享是最主要的目的,是 Twitter 之類社會媒體服務存在的原因。有時候在 Web 站點上更新 Twitter 是非常有好處的 — 特別是像我一樣使用服務來共享信息和資源。
有些人可能會問:“那這有什麼意義呢?” 如果您一直緊跟社會營銷和媒體的發展趨勢,您就會知道,每個人(政府、公司品牌、營銷人員、消費者、各種愛好者)正在加入到 “市場就是對話” 這一潮流中。事實上,關於這一主題,網上的討論是非常多的。
與這些人中的大多數人不同,您是一位技術專家,因此可以很好地衡量這些工具並理解發起對話的形式。這對您的職業生涯是有用的 — 您將是辦公室中惟一理解具體細節的人,而不是僅僅大談 “社會媒體怎樣怎樣。” 此外,了解 Twitter 對擴展您的技能也很有用。
Twitter API 的技術背景
從表面上看,Twitter 基本上是一個精簡版的博客服務。您擁有發布 tweet 的用戶。Tweet 被限制為 140 個字元,帶有日期和時間戳。用戶可以相互追隨,這實際上就是一個簡化的聯合(syndication)服務。與 Twitter 帳戶及相關的時間線和 tweet 有關的信息不僅對標準 Web 界面可用,而且可以通過 Twitter API 被第三方應用程序所用。這個 API 通過具象狀態傳輸(Representational State Transfer,REST)或搜索 API 公開 Teitter 數據和服務。
本文只討論 REST API,因為您確實不需要利用搜索功能來發布 tweet 的 RSS 提要。毋庸多言,搜索 API 非常有用,它提供 Atom 和 JavaScript Serialized Object Notation(JSON)格式的數據,允許各種搜索條件(包含一個單詞的 tweet,來自某一特定用戶,發送給某一特定用戶,引用了某個特定用戶,包含一個 hashtag,或同時包含以上所有條件)。REST API 同樣有用,它提供 RSS、XML、JSON 和 Atom 格式的數據。
REST API 使用 HTTP 基本身份驗證作為它的身份驗證模式,大多數庫和實用工具的啟動都需要使用 Twitter 用戶名和密碼。如果沒有 Twitter 帳戶,則需要一個帳戶來啟動程序,或者至少訪問 Twitter 帳戶的身份驗證憑證。但是,如 Twitter API 的 wiki 所述:所有響應都與進行身份驗證的用戶的上下文有關。如果試著從您沒有追隨的受保護用戶獲得信息,請求就會失敗。
REST API 的名稱表明,Twitter API 試著符合具象狀態傳輸的設計原理。REST 通常用來不確切地描述一類簡單的介面,它們通過 HTTP 在沒有任何額外層(如 SOAP 或 cookies)的情況下傳遞特定於域的數據。RESTful 服務通常涉及一個或更多的資源,每一個都與一些可獨立定址的內容關聯 — 即統一資源標識符(Uniform Resource Identifier,URI)。在 Twitter API 上下文中,有多種 RESTful 服務可用於提取有關用戶、追隨者、時間線等內容的信息。
使用 Twitter 涉及一些熟悉的方法。在許多情況下,您可以從一種數據類型切換到另一種數據類型,只需更改文件擴展名即可。需要 Atom 而不是 RSS?切換文件擴展名就行,而且,如果有特定的方法支持它,那麼就獲得了新格式化的數據流。將請求參數轉換為 8 位 Unicode 轉換格式(Unicode Transformation Format,UTF-8)並使用統一資源定位符(Uniform Resource Locator,URL)編碼也是一個不錯的主意,特別是在這些請求參數涉及複雜的字元串時。
特別注意,Twitter API 支持以下請求類型:
如果試圖使用 POST 操作檢索數據,API 就會返回一條錯誤 — 在調試時,最好從帶有請求類型的匹配方法入手。
與其他使用 HTTP 的 REST 服務一樣,Twitter API 使用一組狀態碼和錯誤消息。Twitter API 為每個請求返回標準且對應的 HTTP 狀態碼,如 表 1 中所述。這使得使用 Twitter API 就好像使用其他您已經習慣使用的基於 HTTP 的操作一樣(如果不是無法區別的話),如 Asynchronous JavaScript + XML (Ajax) 和簡單的同步 GET 和 POST 操作。
狀態碼 | 說明 |
---|---|
200 OK | 一切正常。 |
304 Not Modified | 沒有新的數據返回。 |
400 Bad Request | 無效的請求,給出一些詳細信息。如果超出速率限制,也會得到這個狀態碼(會更詳細一點)。 |
401 Not Authorized | 忘記提供身份驗證詳細信息,或者提供的身份驗證詳細信息無效。 |
404 Not Found | 請求的 URI 不存在(也就是說,用戶不存在,或者數據服務不支持)。 |
500 Internal Server Error | 這通常是 Twitter 方面的問題。 |
502 Bad Gateway | Twitter 被關閉或正在升級。 |
503 Service Unavailable | Twitter 服務超載。 |
錯誤消息通常以請求的格式返回。如果請求 XML,得到的所有錯誤消息都將是 XML 格式的。例如,清單 1 是 Twitter API wiki 發布的一條錯誤消息的一個片段。
<?xml version="1.0" encoding="UTF-8"?> <hash> Ƞ<request>/direct_messages/destroy/111.xml</request> Ƞ<error>No direct message with that ID found.</error> </hash> |
關於速率限制還有最後一點要注意:允許客戶機每小時發出 100 個請求,從他們的第一個請求開始,不包括 POST 更新。未經身份驗證的請求將被跟蹤 IP 地址,而經過身份驗證的請求則對發出請求的用戶進行跟蹤。只要超過速率限制,Twitter 就會返回一條 400 錯誤消息,因此您需要考慮在您這一端實現本地緩存。公共時間線會被 Twitter 緩存至少 60 秒,因此請求更新是非常浪費時間的。
但是,如果您發現自己突然到達速率限制時,可以從 Twitter 請求白名單(請參閱 參考資料)。您會在 48 小時之內得到回復,而請求如果批准的話,您的應用程序將被允許每小時發出多達 20,000 個請求。
![]() ![]() |
使用 Twitter REST API
當我還是一個年輕的 Web 開發人員時,我可以夜以繼日地朝任何指定的方向編碼,完全沒有問題。15 年過去了,我無疑老了許多,不過欣慰的是,我也變聰明了點。儘管我在這裡提供了一些有關某些 Twitter REST API 方法的細節,但這只是供參考之用。最終,您將使用一個極好的 PHP 庫來大大減輕您的工作負擔。
但是,因為引入沒有上下文的庫沒有任何好處,所以下面簡要介紹一些使用更廣泛的 Twitter REST API 方法和調用。
最常用的 API 方法可能是 public_timeline。與其他狀態方法一樣,public_timeline 的格式有 XML、JSON、RSS 和 Atom,同樣地,它也使用 GET 檢索數據。從 http://twitter.com/statuses/public_timeline.xml(或 .rss 等)可獲得該方法。如清單 2 所示,狀態元素基本上包含描述帳戶的節點,並有一個描述用戶的嵌入式用戶節點。
<status> created_at id text source truncated in_reply_to_status_id in_reply_to_user_id favorited <user>> id name screen_name description location profile_image_url url protected followers_count |
另一個比較常用的方法是 friends_timeline,它返回驗證用戶和該用戶的朋友最近發布的 20 個狀態,如果您已經登錄到 Twitter,那麼該方法非常類似於 http://www.twitter.com/home。這個方法可從 http://twitter.com/statuses/friends_timeline.xml(或 .rss、.atom、.json)獲得並通過 GET 請求檢索。您可以插入一些可選參數,如 since(一個 HTTP 修改日期,如 Mon%2C+2+Feb+2009+11%3A45%3A33+GMT)或 page(從時間線中檢索特定的 tweets 頁面)。
然後還有 user_timeline 方法,它類似於 friends_timeline,但被限制為特定用戶的 tweet(您可能已經猜到了)。如果沒有指定 Twitter 用戶名,API 就假定您想檢索驗證用戶的時間線。
還有許多其他可用的方法,當然,以上三個方法已足夠幫助您入門了。現在,像我曾提到的那樣,您無需任何幫助即可使用 Twitter API 了,但這不會使您變成一位高效的開發人員。您有您自己的極限,所以最好使用預先構建好的庫。
幸運的是,有一個非常好的庫可用,即 twitterlibphp(請參閱 參考資料)。下載這個庫,然後將它添加到測試或開發伺服器。在下一節,您將開始使用它。
![]() ![]() |
使用 twitterlibphp
twitterlibphp 庫包含一個方法列表,每個方法都映射到一個 Twitter API 方法。該庫本身處理所有連接、身份驗證、錯誤處理等等。包含此庫並進行身份驗證后,首先從其中一個方法開始。
首先,看看使用 showUser() 方法檢索特定用戶的 XML 狀態會發生什麼。在清單 3 中,只需用帳戶的憑證替換 $user 和 $pw 的值,這樣就可以檢索到狀態信息了。
include_once("twitter.lib.php"); $user = "your-username"; $pw = "your-password"; $twitter = new Twitter($user,$pw); $xml = $twitter->showUser("xml", $user); echo $xml; |
結果在原始輸出中提供了大量信息,在清單 4 所示的 XML 中,您不僅可以看到我的真實姓名、屏幕名和最後一個 tweet,還可以看到我追隨的人、頭像的路徑,甚至我的顏色偏好。
<?xml version="1.0" encoding="UTF-8"?> <user> <id>14129237</id> <name>Thomas Myer</name> <screen_name>myerman</screen_name> <location>Most likely rushing to my next</location> <description>Author, Infopreneur, Blogger, Consultant</description> <profile_image_url>http://s3.amazonaws.com/twitter_production/profile_images/ 74029317/myerman_gmail.com_eef446f6_normal.jpg</profile_image_url> <url>http://www.tripledogs.com</url> <protected>false</protected> <followers_count>55</followers_count> <profile_background_color>FFFFFF</profile_background_color> <profile_text_color>5F5454</profile_text_color> <profile_link_color>A18FB9</profile_link_color> <profile_sidebar_fill_color>082C35</profile_sidebar_fill_color> <profile_sidebar_border_color>120E26</profile_sidebar_border_color> <friends_count>16</friends_count> <created_at>Wed Mar 12 02:10:30 +0000 2008</created_at> <favourites_count>3</favourites_count> <utc_offset>-21600</utc_offset> <time_zone>Central Time (US & Canada)</time_zone> <profile_background_image_url>http://static.twitter.com/images/themes/theme1/bg.gif </profile_background_image_url> <profile_background_tile>false</profile_background_tile> <following>false</following> <notifications>false</notifications> <statuses_count>427</statuses_count> <status> <created_at>Sun Feb 01 21:29:17 +0000 2009</created_at> <id>1167762741</id> <text>@adonoho [tweet snipped for privacy].</text> <source>web</source> <truncated>false</truncated> <in_reply_to_status_id>1167558714</in_reply_to_status_id> <in_reply_to_user_id>882801</in_reply_to_user_id> <favorited>false</favorited> <in_reply_to_screen_name>adonoho</in_reply_to_screen_name> </status> </user> |
詳細給出這些信息后,使用 SimpleXML 處理這個 XML 節點集就很簡單了,而且使用它可以做一些有用的事情。例如,您可以輕鬆地編寫一個顯示 screen_name 元素以及 statuses_count 的工具,可能還會顯示最近狀態的 created_at 節點。
同樣有趣的是,您需要的是 RSS。具體來說,您需要檢索用戶的時間線。擁有 RSS 格式的時間線后,就可以將它作為一個側欄小部件、一個獨特頁面或任何其他可定址的目標,放在 PHP 驅動站點上。
要實現該操作,請更改上面的例子,使用庫的 getUserTimeline() 方法,如清單 5 所示。
include_once("twitter.lib.php"); $user = "your-username"; $pw = "your-password"; $twitter = new Twitter($user,$pw); $rss = $twitter->getUserTimeline("rss", $user); echo $rss; |
如您所見,這個函數返回可立即使用的 RSS。
<?xml version="1.0" encoding="UTF-8"?> <rss version="2.0"> <channel> <title>Twitter / myerman</title> <link>http://twitter.com/myerman</link> <description>Twitter updates from Thomas Myer / myerman.</description> <language>en-us</language> <ttl>40</ttl> <item> <title>myerman: just got my copy of groundswell...also, just got back from seeing Taken. Liam Neeson kicks butt!</title> <description>myerman: just got my copy of groundswell...also, just got back from seeing Taken. Liam Neeson kicks butt!</description> <pubDate>Sun, 01 Feb 2009 04:16:55 +0000</pubDate> <guid>http://twitter.com/myerman/statuses/1166126064</guid> <link>http://twitter.com/myerman/statuses/1166126064</link> </item> <item> <title>myerman: For those of us trying to learn Objective-C - some libraries. http://tinyurl.com/dkaj4m</title> <description>myerman: For those of us trying to learn Objective-C - some libraries. http://tinyurl.com/dkaj4m</description> <pubDate>Fri, 30 Jan 2009 20:06:13 +0000</pubDate> <guid>http://twitter.com/myerman/statuses/1162686918</guid> <link>http://twitter.com/myerman/statuses/1162686918</link> </item> <item> <title>myerman: RT @andyhunter Google Chief Economist on innovation: We’re in the middle of .. a period of “combinatorial innovation.” http://bit.ly/xgpN</title> <description>myerman: RT @andyhunter Google Chief Economist on innovation: We’re in the middle of .. a period of “combinatorial innovation.” http://bit.ly/xgpN</description> <pubDate>Fri, 30 Jan 2009 15:35:18 +0000</pubDate> <guid>http://twitter.com/myerman/statuses/1161902779</guid> <link>http://twitter.com/myerman/statuses/1161902779</link> </item> <item> <title>myerman: A-Team movie out next year? I love it when a plan comes together. http://tinyurl.com/ahckx9</title> <description>myerman: A-Team movie out next year? I love it when a plan comes together. http://tinyurl.com/ahckx9</description> <pubDate>Thu, 29 Jan 2009 19:21:34 +0000</pubDate> <guid>http://twitter.com/myerman/statuses/1159386717</guid> <link>http://twitter.com/myerman/statuses/1159386717</link> </item> <item> <title>myerman: @andyhunter @cesart it's the pulvinar that gets you in trouble... every time!</title> <description>myerman: @andyhunter @cesart it's the pulvinar that gets you in trouble... every time!</description> <pubDate>Thu, 29 Jan 2009 16:44:30 +0000</pubDate> <guid>http://twitter.com/myerman/statuses/1158923928</guid> <link>http://twitter.com/myerman/statuses/1158923928</link> </item> <item> <title>myerman: Create a manga avatar of yourself. http://www.faceyourmanga.com </title> <description>myerman: Create a manga avatar of yourself. http://www.faceyourmanga.com </description> <pubDate>Thu, 29 Jan 2009 16:43:55 +0000</pubDate> <guid>http://twitter.com/myerman/statuses/1158922223</guid> <link>http://twitter.com/myerman/statuses/1158922223</link> </item> <item> <title>myerman: Zombies ahead on Lamar & 15th....silly hackers! http://tinyurl.com/c2s3nw</title> <description>myerman: Zombies ahead on Lamar & 15th....silly hackers! http://tinyurl.com/c2s3nw</description> <pubDate>Thu, 29 Jan 2009 13:21:24 +0000</pubDate> <guid>http://twitter.com/myerman/statuses/1158382096</guid> <link>http://twitter.com/myerman/statuses/1158382096</link> </item> <item> <title>myerman: Obama's Mac: http://tinyurl.com/b4hsza</title> <description>myerman: Obama's Mac: http://tinyurl.com/b4hsza </description> <pubDate>Thu, 29 Jan 2009 13:17:58 +0000</pubDate> <guid>http://twitter.com/myerman/statuses/1158375012</guid> <link>http://twitter.com/myerman/statuses/1158375012</link> </item> <item> <title>myerman: OK, looks like I'll be speaking on Saturday at SxSW 2009. More details for the freelancer in your life: http://tinyurl.com/df8my9</title> <description>myerman: OK, looks like I'll be speaking on Saturday at SxSW 2009. More details for the freelancer in your life: http://tinyurl.com/df8my9</description> <pubDate>Wed, 28 Jan 2009 22:39:29 +0000</pubDate> <guid>http://twitter.com/myerman/statuses/1156744158</guid> <link>http://twitter.com/myerman/statuses/1156744158</link> </item> ...snip </channel> </rss> |
有一點要注意:在達到速率限制之前,您不會只想重複調用這個函數。相反,您需要稍微控制一下請求。使用 rateLimitStatus() 方法和一些自己定製的(home-rolled)緩存可以做一些更聰明的事情,以實現本地緩存效果。
如清單 7 所示,rateLimitStatus() 方法是一個簡單的請求,您可以使用它來檢查您是否已經達到了速率限制 — 檢查速率限制狀態不會對您不利。您所要做的只是提供一個格式,該函數會完成所有其他事情。
include_once("twitter.lib.php"); $user = "your-username"; $pw = "your-pw"; $twitter = new Twitter($user,$pw); $status = $twitter->rateLimitStatus("xml"); echo $status; |
運行 rateLimitStatus() 方法時,會返回以下 XML。
<?xml version="1.0" encoding="UTF-8"?> <hash> <hourly-limit type="integer">100</hourly-limit> <reset-time type="datetime">2009-02-02T05:44:45+00:00</reset-time> <reset-time-in-seconds type="integer">1233553485</reset-time-in-seconds> <remaining-hits type="integer">99</remaining-hits> </hash> |
您需要的是 remaining-hits 節點內的值。如果該值達到 5 左右(或者可能是 10),就轉到緩存的 RSS 提要。有了這個 XML 節點集后,您所要做的就是載入 SimpleXML 來快速解析速率限制狀態。當然,如果您不熟悉 XML 的用法,那麼最好解析為 JSON。
使用 JSON 格式運行相同的代碼將得到精簡得多的語句:
{"remaining_hits":95,"hourly_limit":100,"reset_time":"Mon Feb 02 05:44:45 +0000 2009", "reset_time_in_seconds":1233553485} |
花些時間用逗號將這個字元串分開,然後再用冒號獲取 remaining_hits 的值。當然這很簡單。但是,如果您運行的是 PHP V5.2.0 或更高版本,可能已經能使用 json_decode() 方法了。如清單 9 所示,您所要做的只是使用該函數得到 remaining_hits 數字,然後使用一個簡單的 if 語句看看該數字是接近於 10 還是更小。如果不是,從 Twitter 拖出 RSS 提要,不過將它保存到一個文件供稍後使用。如果小於 10,就使用本地緩存的保存后的 RSS 文件。
include_once("twitter.lib.php"); $user = "your-username"; $pw = "your-password"; $twitter = new Twitter($user,$pw); $status = $twitter->rateLimitStatus("json"); $fileName = $user.".rss"; $json_dump = json_decode($status); $remaining = $json_dump->remaining_hits; if ($remaining <= 10){ $fh = fopen($fileName, 'r'); $rssData = fread($fh, filesize($fileName)); fclose($fh); echo $rssData; }else{ $rss = $twitter->getUserTimeline("rss", $user); //write to file //in case we need it! $fh = fopen($fileName,'w') or die("can't write to file"); fwrite($fh,$rss); fclose($fh); echo $rss; } |
剩下要做的是為 PHP 文件指定一個合適的名稱(例如,twitterfeed.php),然後合理使用它,即將它作為另一個訂閱選項提供給用戶,提供 WordPress 側欄小部件或諸如此類的任何對象。
![]() ![]() |
結束語
通過本文的學習,您初步了解了 Twitter 的工作方式 — 具體來說,您了解了 REST API 公開的內容。您還學習了如何使用公共可用的 PHP 庫來簡化工作。如果幸運的話,您學到的知識足以構建自己的應用程序和實用工具。(責任編輯:A6)
[火星人 ] 使用 PHP 將 Twitter 轉換為 RSS已經有741次圍觀