Commit 4ea85875 authored by DANIEL DIAZ SANCHEZ's avatar DANIEL DIAZ SANCHEZ
Browse files

Update README.md

parent 0b6fd6d3
......@@ -178,10 +178,331 @@ public class TwitterCrawler {
Sustituye `oauth_consumer_key` y `oauth_consumer_secret` por los valores de tu aplicación y pruébalo.
### Gestión de tweets con Json
Los tweets devueltos por Twitter (en general cualquier información que devuelva el API). Creamos dos clases para guardar, por un lado el Tweet y por otro lado el usuario que lo creó, aunque el primero apunta al segundo. Las clases son las siguientes
```java
package cdistRest;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
public class Tweet {
public static Tweet deserializeJson(String input_json) {
Gson gson = new Gson();
Tweet new_Tweet = gson.fromJson(input_json, Tweet.class);
return new_Tweet;
}
public static List<Tweet> deserializeJsonArray(String input_json) {
Gson gson = new Gson();
Type collectionType = new TypeToken<Collection<Tweet>>(){}.getType();
Collection<Tweet> new_tweet_collection = gson.fromJson(input_json,
collectionType);
ArrayList<Tweet> new_Tweet_list = new ArrayList<Tweet>(
new_tweet_collection);
return new_Tweet_list;
}
@SerializedName("geo")
public String geo;
@SerializedName("in_reply_to_status_id")
public String in_reply_to_status_id;
@SerializedName("truncated")
public String truncated;
@SerializedName("created_at")
public String created_at;
@SerializedName("retweet_count")
public String retweet_count;
@SerializedName("in_reply_to_user_id")
public String in_reply_to_user_id;
@SerializedName("id_str")
public String id_str;
@SerializedName("place")
public String place;
@SerializedName("favorited")
public boolean favorited;
@SerializedName("source")
public String source;
@SerializedName("in_reply_to_screen_name")
public String in_reply_to_screen_name;
@SerializedName("in_reply_to_status_id_str")
public String in_reply_to_status_id_str;
@SerializedName("id")
public long id;
@SerializedName("contributors")
public String contributors;
@SerializedName("coordinates")
public String coordinates;
@SerializedName("retweeted")
public boolean retweeted;
@SerializedName("text")
public String text;
@SerializedName("profile_image_url")
public String profile_image_url;
// public user user;
public User user;
}
```
```java
package cdistRest;
import com.google.gson.annotations.SerializedName;
public class User {
@SerializedName("friends_count")
public int friends_count;
@SerializedName("profile_background_color")
public String profile_background_color;
@SerializedName("profile_background_image_url")
public String profile_background_image_url;
@SerializedName("created_at")
public String created_at;
@SerializedName("description")
public String description;
@SerializedName("favourites_count")
public int favourites_count;
@SerializedName("lang")
public String lang;
@SerializedName("notifications")
public boolean notifications;
@SerializedName("id_str")
public String id_str;
@SerializedName("default_profile_image")
public boolean default_profile_image;
@SerializedName("profile_text_color")
public String profile_text_color;
@SerializedName("default_profile")
public boolean default_profile;
@SerializedName("show_all_inline_media")
public boolean show_all_inline_media;
@SerializedName("contributors_enabled")
public boolean contributors_enabled;
@SerializedName("geo_enabled")
public boolean geo_enabled;
@SerializedName("screen_name")
public String screen_name;
@SerializedName("profile_sidebar_fill_color")
public String profile_sidebar_fill_color;
@SerializedName("profile_image_url")
public String profile_image_url;
@SerializedName("profile_background_tile")
public boolean profile_background_tile;
@SerializedName("follow_request_sent")
public boolean follow_request_sent;
@SerializedName("url")
public String url;
@SerializedName("statuses_count")
public int statuses_count;
@SerializedName("following")
public boolean following;
@SerializedName("time_zone")
public String time_zone;
@SerializedName("profile_link_color")
public String profile_link_color;
@SerializedName("protected")
public boolean protectedd;
@SerializedName("verified")
public boolean verified;
@SerializedName("profile_sidebar_border_color")
public String profile_sidebar_border_color;
@SerializedName("followers_count")
public int followers_count;
@SerializedName("location")
public String location;
@SerializedName("name")
public String name;
@SerializedName("is_translator")
public boolean is_translator;
@SerializedName("id")
public long id;
@SerializedName("listed_count")
public int listed_count;
@SerializedName("profile_use_background_image")
public boolean profile_use_background_image;
@SerializedName("utc_offset")
public int utc_offset;
}
```
### Anade una consulta al API de Twetter
Vamos a probar con la función del API [get user timeline](https://dev.twitter.com/rest/reference/get/statuses/user_timeline) que permite obtener los tweets más recientes de un usuario.
Inspecciona la página del API. Revisa los parámetros de la llamada a esa función del API Rest, verás que puedes usar `user_id` que es el ID de twetter (poco conocido, un número) o bien el `screen_name' que es el nombre de la cuenta de twitter que se muestra por internet, por ejemplo @realmadrid.
Además se pueden especificar el número de Tweets a obtener.
Para obtener 2 tweets de la cuenta @realmadrid usa el siguiente código:
```java
package cdistRest;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
import org.apache.commons.codec.binary.Base64;
import com.google.gson.Gson;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import com.mashape.unirest.request.GetRequest;
import com.mashape.unirest.request.body.RequestBodyEntity;
public class TwitterCrawler {
private static final String oauth_consumer_key = "WNwl0uA9r6EimdvpBqWYSaMPC";
private static final String oauth_consumer_secret = "JGeVLV7zv2XT9jVKsywvKsNZ0tQQ8L7V2GMAdqIQjLG9QCceFc";
public class BearerToken
{
private String access_token;
private String token_type;
}
public static String deserializeJson(String input_json)
{
Gson gson = new Gson();
BearerToken new_bearerToken = gson.fromJson(input_json, BearerToken.class);
return new_bearerToken.access_token;
}
public static void main(String args[]) throws IOException {
try {
/* get bearer token according to https://dev.twitter.com/oauth/application-only */
String URLEncoderConsumerKey = URLEncoder.encode(oauth_consumer_key, "UTF-8");
String URLEncoderConsumerSecret = URLEncoder.encode(oauth_consumer_secret, "UTF-8");
String AuthorizationHeader = URLEncoderConsumerKey+":"+URLEncoderConsumerSecret;
String AuthorizationHeaderB64 = Base64.encodeBase64String(AuthorizationHeader.getBytes("UTF8"));
System.out.println(AuthorizationHeaderB64);
RequestBodyEntity postReq = Unirest.post("https://api.twitter.com/oauth2/token")
.header("User-Agent","TwitterApp")
.header("host", "api.twitter.com")
.header("Authorization", "Basic " + AuthorizationHeaderB64)
.header("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")
.body("grant_type=client_credentials");
HttpResponse<String> res = postReq.asString();
String bearer_token = TwitterCrawler.deserializeJson(res.getBody());
/* we now have a brearer token so can make requests to Twitter */
/* https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=realmadrid&count=2 */
HttpResponse<String> json_str_Response = null;
GetRequest getReq = null;
getReq = Unirest.get("https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name={screen_name}&count={count}")
.routeParam("screen_name","realmadrid")
.routeParam("count","2")
.header("Authorization", "Bearer " + bearer_token);
System.out.println("Request to: " + getReq.getUrl());
System.out.println("Authorization header Bearer " + bearer_token);
json_str_Response = getReq.asString();
System.out.println("Json : " + json_str_Response.getBody());
List<Tweet> tweet_list = Tweet.deserializeJsonArray(json_str_Response.getBody());
Unirest.shutdown();
} catch (UnirestException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
```
Observa, depurando paso a paso y usando break points (en ocasiones entrar dentro de una función con eclipse no funciona - dado que no encuentra el código - lo mejor es usar breakpoints en los métodos en los que queremos parar) lo siguiente:
* Creación de la cabecera de autenticación a partir del objeto BearerToken
* Como se procesa un array de tweets en Json usando el método deserializeJsonArray de la clase Tweet
* Observa cómo GSON automáticamente procesa el objeto User que está dentro de la cadena de texto json de cada tweet
* Observa cómo se procesan los campos, para ver claramente como es el JSON de partida usa un parser online como el de http://json.parser.online.fr/
### Peticiones con cursores
La función del API descrita en https://dev.twitter.com/rest/reference/get/statuses/user_timeline tiene un límite de 200 tweets por petición.
El problema es que los API REST no tienen estado, entonces, ¿cómo bajar los 3200?
Para ello, es necesario usar cursores, elementos que le informen a Twitter a partir de qué Tweet deseas obtener los siguientes 200.
Para ello utilizamos el parámetro max_id de la petición, usando la información contenida aquí https://dev.twitter.com/rest/public/timelines
Usemos una cuenta popular, cualquiera con más de 3200 Tweets. Para ello usa cualquiera de las más populares del mundo (yo voy a usar @realmadrid).
De todos los tweets recibidos, hay que buscar cuál de ellos tiene menor id y usarlo como parámetro (restándole 1) para la siguiente petición.
Averigua como podrías obtener más Tweets haciendo peticiones poco a poco con el método explicado (lo veremos en detalle el proximo día)
## Importa el proyecto completo en Eclipse desde este repositiorio
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment