国内研究weibo的人比较多,资料也相对较多,但是twitter的资料相对较少。今天简单说一下twitter api的使用。最近一小需求,采集含有指定关键词的twitter数据,瞬间想到写个爬虫来抓取,后来突然想到twitter应该有open api可用。使用了vpn翻墙之后简单的了解了twitter.com,决定直接使用 twitter api。由于twitter的open api现在也是基于oauth协议的,因此使用流程和国内一些社区比如说人人网,weibo的api的过程类似。
要想使用twitter api,首先要有twitter的账号,并且在twitter deveoper中创建应用,地址:https://apps.twitter.com/app/new
上边怎么填就不说了,创建成功之后可以获得应用的信息。创建成功之后你会获得Consumer key和Consumer secret。将这两个数据保存下来。如下图:
为了方便用java操作,这里我们使用开源的twitter4j,最新版本为:twitter4j-4.0.2。(https://github.com/twitter/twitter4j)Twitter4J也就对Twitter
的API进行了java封装,这样的话我们就可以很方便的使用java才操作 twitter api。twitter4j-4.0.2.zip之后,我们可以看到说明文档和实例代码,当然也包括源代码。糟糕的是我觉得说明文档写的并不详细,建议直接看示例代码和源代码就好。
首先我们创建一个java项目(当然你也可以创建web应用)并导入相关jar,然后在项目路径下创建twitter4j.properties文件,里边填写刚才保存下的Consumer Key和Consumer Secret。
项目结构:
twitter4j.properties:
oauth.consumerSecret=gLpOB2rbyVTVc6DgmL***HQJzTpqTDMU5nOlrfs2ksI7muWZmQ oauth.accessToken=2926555458-DwB2WcX8eF***hxRLkRZ6xIkCNHVNwj43e5CBWb
然后和所有基于oauth协议的开发api一样,我们需要获取授权信息。代码如下:
import java.awt.Desktop; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.URI; import java.net.URISyntaxException; import java.util.Properties; import twitter4j.Twitter; import twitter4j.TwitterException; import twitter4j.TwitterFactory; import twitter4j.auth.AccessToken; import twitter4j.auth.RequestToken; /** * @ClassName: GetAccessToken * @Description:获取授权信息 * @author God * @date 2014-12-12 上午11:19:53 * */ public class GetAccessToken { public static void main(String[] args) { String cPath="D:\\A_WorkSpace\\workspace14_CareerPredict\\twitter\\src\\twitter4j.properties"; File file = new File(cPath); Properties prop = new Properties(); InputStream is = null; OutputStream os = null; try { if (file.exists()) { is = new FileInputStream(file); prop.load(is); } if (args.length < 2) { if (null == prop.getProperty("oauth.consumerKey") && null == prop.getProperty("oauth.consumerSecret")) { System.out.println( "Usage: java twitter4j.examples.oauth.GetAccessToken [consumer key] [consumer secret]"); System.exit(-1); } } else { prop.setProperty("oauth.consumerKey", args[0]); prop.setProperty("oauth.consumerSecret", args[1]); os = new FileOutputStream("twitter4j.properties"); prop.store(os, "twitter4j.properties"); } } catch (IOException ioe) { ioe.printStackTrace(); System.exit(-1); } finally { if (is != null) { try { is.close(); } catch (IOException ignore) { } } if (os != null) { try { os.close(); } catch (IOException ignore) { } } } try { Twitter twitter = new TwitterFactory().getInstance(); RequestToken requestToken = twitter.getOAuthRequestToken(); System.out.println("Got access token."); System.out.println("Request token: " + requestToken.getToken()); System.out.println("Request token secret: " + requestToken.getTokenSecret()); AccessToken accessToken = null; BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); while (null == accessToken) { System.out.println("Open the following URL and grant access to your account:"); System.out.println(requestToken.getAuthorizationURL()); try { //调用浏览器访问Twiiter的授权页面,帐号登录成功也就是授权成功后将会跳转回到申请的APP中的Redirect_URI地址,并携带了request_token Desktop.getDesktop().browse(new URI(requestToken.getAuthorizationURL())); } catch (UnsupportedOperationException ignore) { } catch (IOException ignore) { } catch (URISyntaxException e) { throw new AssertionError(e); } //输入浏览器跳转时携带的code参数(应该将Redirect_URI设置成本系统中的一个Servlet的地址,并且下面的代码放到Servlet中来处理授权信息) System.out.print("Enter the PIN(if available) and hit enter after you granted access.[PIN]:"); String pin = br.readLine(); try { if (pin.length() > 0) { accessToken = twitter.getOAuthAccessToken(requestToken, pin); } else { accessToken = twitter.getOAuthAccessToken(requestToken); } } catch (TwitterException te) { if (401 == te.getStatusCode()) { System.out.println("Unable to get the access token."); } else { te.printStackTrace(); } } } System.out.println("Got access token."); System.out.println("Access token: " + accessToken.getToken()); System.out.println("Access token secret: " + accessToken.getTokenSecret()); try { prop.setProperty("oauth.accessToken", accessToken.getToken()); prop.setProperty("oauth.accessTokenSecret", accessToken.getTokenSecret()); os = new FileOutputStream(file); prop.store(os, "twitter4j.properties"); os.close(); } catch (IOException ioe) { ioe.printStackTrace(); System.exit(-1); } finally { if (os != null) { try { os.close(); } catch (IOException ignore) { } } } System.out.println("Successfully stored access token to " + file.getAbsolutePath() + "."); System.exit(0); } catch (TwitterException te) { te.printStackTrace(); System.out.println("Failed to get accessToken: " + te.getMessage()); System.exit(-1); } catch (IOException ioe) { ioe.printStackTrace(); System.out.println("Failed to read the system input."); System.exit(-1); } } }
这里我们解释一下”输入PIN“这里到底是输入什么?很简单就是你在授权页面登陆成功之后,浏览器跳转时携带的code参数,如下图所示:
运行完上面的代码之后,我们的授权信息会被写入到twitter4j.properties文件中:
#twitter4j.properties #Fri Dec 12 11:50:52 CST 2014 <pre name="code" class="html" style="color: rgb(54, 46, 43); font-size: 14px; line-height: 26px;">oauth.consumerSecret=gLpOB2rbyVTVc6DgmL***HQJzTpqTDMU5nOlrfs2ksI7muWZmQ
oauth.accessToken=2926555458-DwB2WcX8eF***hxRLkRZ6xIkCNHVNwj43e5CBWb
oauth.accessTokenSecret=vJsyhLZF3hKLFPUNJINMBI64UgCh***xzJz8p6oxZcS3Ioauth.consumerKey=***7E1l6GHWuMFTwcZ0tIGZhP
下面我们通过调用api来获取包含指定关键词的twitter。(你可以参考实例代码SearchTweets.java)本人代码如下:
import java.util.ArrayList; import java.util.List; import twitter4j.Query; import twitter4j.Query.ResultType; import twitter4j.QueryResult; import twitter4j.Status; import twitter4j.Twitter; import twitter4j.TwitterException; import twitter4j.TwitterFactory; import com.twiter.info.domain.TwitterInfo; import com.twiter.info.search.Search; import com.twiter.info.utils.DateUtil; import com.twiter.info.utils.ParserUtil; public class SearchOnGetImpl implements Search{ private Twitter twitter = new TwitterFactory().getInstance(); private QueryResult result; public SearchOnGetImpl() { } @Override public <T> List<T> search(String key) { return search(key, 1000, null, null); } @Override public <T> List<T> search(String key, int count, String sinceDate) { return search(key, count, sinceDate, null); } @Override public <T> List<T> search(String key, int count, String sinceDate, String endDate) { List<TwitterInfo> infos=new ArrayList<>(); Query query=new Query(); try { query.setResultType(ResultType.mixed); query.setQuery(key); query.setCount(100);//设置每次获取数量 if(sinceDate!=null){ query.setSince(sinceDate); } if(endDate!=null){ query.until(endDate); } do { result = twitter.search(query); List<Status> tweets = result.getTweets(); String num = result.getQuery(); int level = result.getAccessLevel(); infos.addAll(res2TwitterInfos(tweets)); if(infos.size()>=count)break; } while ((query = result.nextQuery()) != null); } catch (TwitterException te) { te.printStackTrace(); } return (List<T>) infos; } /** * @Title: res2TwitterInfos * @Description: 转换为目标实体类 * @param tweets * @return List<TwitterInfo> */ public List<TwitterInfo> res2TwitterInfos(List<Status> tweets){ TwitterInfo info=null; List<TwitterInfo> infos=new ArrayList<TwitterInfo>(); for (Status tweet : tweets) { info=new TwitterInfo(); info.setId(String.valueOf(tweet.getId())); info.setContent(ParserUtil.E2C(tweet.getText())); info.setDate(DateUtil.date2StandardFormat(tweet.getCreatedAt())); info.setClient(ParserUtil.clean(tweet.getSource())); infos.add(info); } return infos; } @Override public <T> List<T> search(String key, int count) { return this.search(key, count, null, null); } public static void main(String[] args) { new SearchOnGetImpl().search("fe",5000); } }
ok,到现在为止我们便可获取包含fe关键词的twitter数据。但是要注意,这种方式只能获取一周之内的twitter数据。要想不断的获取的话,只能采取另外的方案,通过调用Streaming
apis不断的获取twitter,然后自己再过滤。可以参考PrintSampleStream.java实例代码。
如果想要完整项目可联系我索取。