... | ... | @@ -105,8 +105,7 @@ Para el desarrollo del proyecto, podemos establecer tres partes bien diferenciad |
|
|
2. Procesamiento de datos: Una vez que tenemos el fichero .csv con el nombre del usuario que publicó el tweet junto con su mensaje, indicaremos las palabras que queremos encontrar dentro de los tweets relacionadas con las empresas y en el momento que se produzca una concidencia se sumarán tantos puntos como valoración tenga el usuario según otro fichero donde se indique. Si el usuario no se encuentra en dicho fichero, se le asignará una puntuación de 1 por defecto.
|
|
|
3. Presentación de resultados: Una vez que Hadoop consiga procesar los tweets y obtener todos los puntos en el bloque anterior, se generará un fichero de salida que se procesará para generar un fichero HTML con los resultados que será el que se muestre en pantalla.
|
|
|
|
|
|
Además, para la ejecución del proyecto se han desarrollado scripts que automatizan el proceso. Podemos ver un esquema de los distintos procesos en el siguiente diagrama de bloques:
|
|
|
|
|
|
Además, para la ejecución del proyecto se han desarrollado scripts que automatizan el proceso.
|
|
|
|
|
|

|
|
|
|
... | ... | @@ -128,8 +127,12 @@ En primer lugar, trataremos la descarga de Tweets, para la cual nos hemos apoyad |
|
|
|
|
|
En nuestro código utilizaremos llamadas de forma asíncrona para la descarga del user timeline de distintos usuarios. El uso de control de páginas también se usará para poder obtener todos los Tweets deseados.
|
|
|
|
|
|
#### Descarga de tweets
|
|
|
|
|
|
Para empezar disponemos de la clase *TwitterCrawler.java* que es la clase principal que se encarga de llamar a métodos de otras clases que descarguen los tweets. El código de la misma es el siguiente:
|
|
|
|
|
|
**NOTA: Si se quiere probar el código con los scripts sin realizar grandes modificaciones se recomienda que todo el código de la carpeta "tweets" esté dentro de una carpeta llamada "compdist\_business\_analysis\_tweets" dentro del $HOME.**
|
|
|
|
|
|
package tweets_cd;
|
|
|
|
|
|
import twitter4j.AsyncTwitter;
|
... | ... | @@ -409,6 +412,7 @@ Sin embargo, aun cambiado de opción no podemos evitar las limitaciones. Ahora e |
|
|
http://www.google.co.jp/search?q=506c3b98 or
|
|
|
http://www.google.co.jp/search?q=105d1078
|
|
|
|
|
|
#### Almacenamiento en la base de datos
|
|
|
Una vez que se descargan los tweets se guardan en la base de datos MongoDB, pero siguiendo la estructura del objeto ContentedorTweet. Podemos ver el contenido en *ContenedorTweet:java*.
|
|
|
|
|
|
package tweets_cd;
|
... | ... | @@ -472,12 +476,16 @@ Si falla el anterior comando porque se halla cerrado bruscamente la base de dato |
|
|
Para detener la base de datos de forma limpia, NO debemos utilizar CTRL-C, sino el siguiente comando:
|
|
|
> /home/teleco/cdtools/mongodb/bin/mongod --shutdown --dbpath data
|
|
|
|
|
|
#### Exportación de tweets en .csv
|
|
|
|
|
|
Por último, todos los tweets que se encuentran en la base de datos los exportaremos a un fichero con extensión .csv mediante *mongoexport*. El comando que permite hacer esta operación es:
|
|
|
|
|
|
> mongoexport --db Tweets --collection ContenedorTweet --csv -f "user","msg" -out /home/teleco/compdist_business_analysis_tweets/datos.csv
|
|
|
|
|
|
Indicamos el tipo de objeto de la colección, que en este caso es ContenedorTweet, los campos que queremos en la salida (solo nos interesa el usuario y el mensaje) y la ruta de salida es la que le indiquemos.
|
|
|
|
|
|
#### Automatización en la descarga de tweets
|
|
|
|
|
|
Para automatizar todas las operaciones descritas en este bloque, dentro de la carpeta de scripts, existe uno llamado "tweets.sh", que al ejecutarlo se encarga automáticamente de arrancar la base de datos, ejecutar el código Java, exportar el .csv y finalmente parar la base de datos de forma limpia. El contenido del mismo es:
|
|
|
|
|
|
#!/bin/bash
|
... | ... | @@ -503,4 +511,367 @@ Para automatizar todas las operaciones descritas en este bloque, dentro de la ca |
|
|
|
|
|
exit
|
|
|
|
|
|
De aquí simplemente hacemos notar que para que fucione es necesario cambiar el /home/teleco por el directorio raíz correspondiente y seguir la estructura de ficheros que hemos comentado. |
|
|
\ No newline at end of file |
|
|
De aquí simplemente hacemos notar que para que fucione es necesario cambiar el /home/teleco por el directorio raíz correspondiente y seguir la estructura de ficheros que hemos comentado.
|
|
|
|
|
|
#### Aplicación práctica en el análisis
|
|
|
Aunque se ha podido comprobar que el dataset de tweets se puede conseguir con cualquier tipo de datos, lo que dota de mayor extensibilidad al programa, la aplicación con la que se diseñó este bloque es la de descargar tweets de distintas entidades a nivel mundial, que tuvieran influencia para que sus menciones a otras fueran relevantes.
|
|
|
|
|
|
De este modo, fue elaborada una lista de entidades con sus respectivas cuentas en twitter. Dichas cuentas fueron escritas en el fichero *cuentas\_twitter.txt* y se obtuvieron unos 81000 tweets tras superar en 2 ocasiones el límite de los 36000 tweets que comentamos. La lista de entidades usada fue la siguiente:
|
|
|
|
|
|
1. Deutsche Bank (@DeutscheBank)
|
|
|
2. HSBC Holdings (@HSBC_Press)
|
|
|
3. BNP Paribas (@BNPParibas_com)
|
|
|
4. Industrial and Commercial Bank of China (@icbc)
|
|
|
5. Crédit Agricole (@CreditAgricole)
|
|
|
6. Barclays Group (@Barclays)
|
|
|
7. Royal Bank of Scotland (@RBSGroup)
|
|
|
8. JPMorgan Chase (@jpmorgan)
|
|
|
9. Bank of America (@bankofamerica)
|
|
|
10. Bank of China (@chinabankph)
|
|
|
11. Citigroup (@Citi)
|
|
|
12. ING Group (@ING_news)
|
|
|
13. Banco Santander (@bancosantander)
|
|
|
14. Société Générale (@SocieteGenerale )
|
|
|
15. UBS (@UBS)
|
|
|
16. Norges Bank Investment Management (NBIM) (@NorgesBank)
|
|
|
17. ICBC (@Fundacion_icbc)
|
|
|
18. Berkshire Hathaway (@BHHSRealEstate)
|
|
|
19. Exxon Mobil (@exxonmobil)
|
|
|
20. General Electric (@generalelectric)
|
|
|
21. Wells Fargo (@wellsfargo)
|
|
|
22. PetroChina (@chinapetro)
|
|
|
23. Royal Dutch Shell (@royaldutch)
|
|
|
24. Toyota Motor (@Toyota__Motors)
|
|
|
25. Apple (@AppStore)
|
|
|
26. BP (@BP_America)
|
|
|
27. Chevron (@Chevrton)
|
|
|
28. Volkswagen Group (@Volkswagen)
|
|
|
29. Wal-Mart Stores (@WalmartHub
|
|
|
30. Deloitte Touche Tohmatsu (@Deloitte)
|
|
|
31. KPMG (@KPMG)
|
|
|
32. Ernst & Young (@Eynews)
|
|
|
33. Inditex (@INDITEXnews)
|
|
|
34. Tesco PLC (@TescoMedia)
|
|
|
35. Costco Wholesale Corporation (@Costco_News)
|
|
|
36. Carrefour (@CarrefourTec)
|
|
|
37. Forbes (@Forbes)
|
|
|
38. Telmex (@Telmex)
|
|
|
39. Real Madrid C.F. (@realmadrid)
|
|
|
40. Barcelona F.C. (@FCBarcelona_es)
|
|
|
41. Manchester United F.C. (@ManUtd)
|
|
|
42. Samsung Electronics (@SamsungMobile)
|
|
|
43. AT&T (@ATT)
|
|
|
44. China Mobile (@MobileChina)
|
|
|
45. Vodafone (@Vodafone_Group)
|
|
|
46. IBM (@IBM)
|
|
|
47. Microsoft (@Microsoft)
|
|
|
48. Siemens (@Siemens)
|
|
|
49. Comcast (@comcast)
|
|
|
50. Telefónica (@Telefonica)
|
|
|
51. Google (@google)
|
|
|
52. Intel (@intel)
|
|
|
53. Cisco Systems (@Cisco)
|
|
|
54. Boeing (@Boeing)
|
|
|
55. América Móvil (@AmericanMovil)
|
|
|
56. Oracle (@Oracle)
|
|
|
57. Hon Hai Precision (@HonHaiPrecision)
|
|
|
58. Hitachi (@HDScorp)
|
|
|
|
|
|
# BLOQUE II: PROCESAMIENTO DE DATOS EN HADOOP.
|
|
|
------------------------------------------------
|
|
|
|
|
|
Con todo el desarrollo comentado hasta el momento, hemos podido conseguir una amplia lista de tweets. Nuestro siguiente paso es el procesado de los mismos. Lo primero que nos planteamos es la forma en la que queremos conseguir los resultados.
|
|
|
|
|
|
En nuestra aplicación, lo que estableceremos será el nombre de 4 compañías importantes en el ámbito IT (Amazon, Apple, Microsoft y Google), aunque tal y como está programado se podría cambiar fácilmente por otras; y trataremos de ver de cuál de las 4 se realizan más menciones en Twitter.
|
|
|
|
|
|
Para ello, puesto que las menciones no tienen que ser exclusivamente del nombre de la compañía, sino de alguno de sus productos, estableceremos una lista de palabras con las que puede estar asociada la compañía de la siguiente forma:
|
|
|
|
|
|
{"Google","Gmail","App Engine","google","gmail","Chrome","chrome","appengine","Drive","Play","Maps","News"},
|
|
|
{"Microsoft","Windows","Office","microsoft","windows"},
|
|
|
{"Amazon","AWS","Kindle","amazon","kindle","AMZN","EC2"},
|
|
|
{"Apple","Mac","iPhone","iOS","iPad","iPod","iTunes","Macintosh","Safari","apple"}
|
|
|
};
|
|
|
|
|
|
De este modo, si encontramos Windows, Office, microsoft o windows en lugar del nombre de la compañía Microsoft, también se nos contará como que ha encontrado una mención.
|
|
|
|
|
|
De la sintaxis utilizada para esta parte, cabe destacar que en al final en los resultados finales se mostrará el nombre de la compañía como el **primero** de los elementos de cada lista. Si se quisiesen añadir más compañías, bastaría con añadir otra línea con elementos entre { }.
|
|
|
|
|
|
También es importante notar que este punto es uno de los más delicados en la aplicación y que podrían dar una mayor dispersión en los resultados. En las primeras pruebas realizadas, los resultados eran muy diferentes debido a esto; y es que si por ejemplo hubiésemos admitido la palabra "office" con la 'o' inicial en minúscula, cualquier entidad que mencionase also sobre sus oficinas (office) le darían puntuación a Microsoft por llamar Office a su suite ofimática. Por este motivo se ha tratado de que cuando hay palabras del uso cotidiano que pueden ser relacionadas con una compañía, que solo se use con mayúsculas puesto que la probabilidad de que alguien utilice la palabra con la letra inicial en mayúscula es menor.
|
|
|
|
|
|
En la búsqueda también se tiene en cuenta que un tweet puede decir "Microsoft acaba de lanzar la nueva versión de Office". En este caso aunque se encuentren dos palabras, como pertenecen al mismo tweets solo se contabilizaría una coincidencia.
|
|
|
|
|
|
Como de toda la lista de usuarios de twitter, no todos ellos tienen la misma importancia (o por ejemplo, los tweets de Microsoft sobre sí misma no pueden valer igual que los que le mencione otra compañía), se ha creado un fichero en el que se establece el valor de cada usuario cuando se produzca una coincidencia en un mensaje procedente de él. El nombre del fichero se llama *cuentas\_valor.txt* y la sintaxis utilizada en su contenido es la siguiente:
|
|
|
|
|
|
> @DeutscheBank,3
|
|
|
> @HSBC_Press,2
|
|
|
> @BNPParibas_com,1
|
|
|
> @icbc,1
|
|
|
> @CreditAgricole,2
|
|
|
> @Barclays,2
|
|
|
> @RBSGroup,2
|
|
|
> @jpmorgan,2
|
|
|
|
|
|
Es decir, se escribe el nombre del usuario de twitter, una coma y el valor de la puntuación que se quiere dar si el mensaje con la coincidencia procede de ese usuario en cada línea. En nuestro ejemplo, hemos dado todas las puntuaciones entre 1 y 3; aunque perfectamente se podría establecer cualquier otro baremo.
|
|
|
|
|
|
El resultado que obtendremos, tendrá finalmente el siguiente formato:
|
|
|
> Amazon puntos
|
|
|
> Apple puntos
|
|
|
> Google puntos
|
|
|
> Microsoft puntos
|
|
|
|
|
|
Donde *puntos* será la puntuación obtenida después del procesamiento.
|
|
|
|
|
|
Para procesar los datos en Hadoop según lo descrito usaremos la clase *WordCount.java*, cuyo código es el siguiente:
|
|
|
|
|
|
package cdist;
|
|
|
|
|
|
import java.io.BufferedReader;
|
|
|
import java.io.File;
|
|
|
import java.io.FileReader;
|
|
|
import java.io.IOException;
|
|
|
|
|
|
|
|
|
|
|
|
import org.apache.hadoop.conf.Configuration;
|
|
|
import org.apache.hadoop.fs.Path;
|
|
|
import org.apache.hadoop.io.IntWritable;
|
|
|
import org.apache.hadoop.io.Text;
|
|
|
import org.apache.hadoop.mapreduce.Job;
|
|
|
import org.apache.hadoop.mapreduce.Mapper;
|
|
|
import org.apache.hadoop.mapreduce.Reducer;
|
|
|
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
|
|
|
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
|
|
|
|
|
|
|
|
|
|
|
|
public class WordCount {
|
|
|
|
|
|
public static final String ruta = "/home/teleco/compdist_business_analysis_tweets/cuenta_valor.txt";
|
|
|
public static final int MAX_CUENTAS = 200;
|
|
|
public static final String[][] empresas = {
|
|
|
{"Google","Gmail","App Engine","google","gmail","Chrome","chrome","appengine","Drive","Play","Maps","News"},
|
|
|
{"Microsoft","Windows","Office","microsoft","windows"},
|
|
|
{"Amazon","AWS","Kindle","amazon","kindle","AMZN","EC2"},
|
|
|
{"Apple","Mac","iPhone","iOS","iPad","iPod","iTunes","Macintosh","Safari","apple"}
|
|
|
};
|
|
|
|
|
|
|
|
|
public static class TokenizerMapper extends
|
|
|
Mapper<Object, Text, Text, IntWritable> {
|
|
|
|
|
|
private Text word = new Text();
|
|
|
|
|
|
public void map(Object key, Text value, Context context)
|
|
|
throws IOException, InterruptedException {
|
|
|
String TempString = value.toString();
|
|
|
String[] parts = TempString.split("[\",\"]");
|
|
|
if (parts.length < 2){
|
|
|
return;
|
|
|
}
|
|
|
String user = "@"+parts[1];
|
|
|
String msg = "";
|
|
|
for (int i = 2; i<parts.length; i++)
|
|
|
msg += parts[i];
|
|
|
|
|
|
for(int i= 0; i<empresas.length;i++){
|
|
|
|
|
|
boolean coincidencia = false;
|
|
|
|
|
|
for(int j=0; j<empresas[i].length;j++){
|
|
|
if (msg.indexOf(empresas[i][j]) != -1){
|
|
|
coincidencia = true;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if(coincidencia){
|
|
|
int puntos = puntuacion(user);
|
|
|
IntWritable points = new IntWritable(puntos);
|
|
|
word.set(empresas[i][0]);
|
|
|
context.write(word,points);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//Obtener usuario y mensaje
|
|
|
//Buscar en el mensaje
|
|
|
//Llamar a una función que devuelva un valor dependiendo del usuario
|
|
|
//si se ha encontrado algo
|
|
|
//En caso positivo se guarda en el contexto; si no no.
|
|
|
|
|
|
}
|
|
|
|
|
|
private static int puntuacion(String user){
|
|
|
File archivo = null;
|
|
|
FileReader fr = null;
|
|
|
BufferedReader br = null;
|
|
|
int contador = 0;
|
|
|
//En caso de error (ej: no exista el fichero), todos los tweets valen lo mismo.
|
|
|
int puntuacion = 1;
|
|
|
|
|
|
try {
|
|
|
archivo = new File(ruta);
|
|
|
fr = new FileReader (archivo);
|
|
|
br = new BufferedReader(fr);
|
|
|
// Lectura del fichero
|
|
|
String linea;
|
|
|
while((linea=br.readLine())!=null){
|
|
|
if (contador >= MAX_CUENTAS){
|
|
|
break;
|
|
|
}
|
|
|
String[] datos = linea.split(",");
|
|
|
String usuario = datos[0];
|
|
|
int points = Integer.parseInt(datos[1].trim());
|
|
|
|
|
|
if(usuario.equals(user)){
|
|
|
puntuacion = points;
|
|
|
break;
|
|
|
}
|
|
|
contador++;
|
|
|
}
|
|
|
}catch(Exception e){
|
|
|
|
|
|
}finally{
|
|
|
// En el finally cerramos el fichero, para asegurarnos
|
|
|
// que se cierra tanto si todo va bien como si salta
|
|
|
// una excepcion.
|
|
|
try{
|
|
|
if( null != fr ){
|
|
|
fr.close();
|
|
|
}
|
|
|
}catch (Exception e2){
|
|
|
e2.printStackTrace();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return puntuacion;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public static class IntSumReducer extends
|
|
|
Reducer<Text, IntWritable, Text, IntWritable> {
|
|
|
private IntWritable result = new IntWritable();
|
|
|
|
|
|
public void reduce(Text key, Iterable<IntWritable> values,
|
|
|
Context context) throws IOException, InterruptedException {
|
|
|
int sum = 0;
|
|
|
for (IntWritable val : values) {
|
|
|
sum += val.get();
|
|
|
}
|
|
|
result.set(sum);
|
|
|
context.write(key, result);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
|
Configuration conf = new Configuration();
|
|
|
Job job = Job.getInstance(conf, "word count");
|
|
|
job.setJarByClass(WordCount.class);
|
|
|
job.setMapperClass(TokenizerMapper.class);
|
|
|
job.setCombinerClass(IntSumReducer.class);
|
|
|
job.setReducerClass(IntSumReducer.class);
|
|
|
job.setOutputKeyClass(Text.class);
|
|
|
job.setOutputValueClass(IntWritable.class);
|
|
|
TextInputFormat.addInputPath(job, new Path(args[0]));
|
|
|
FileOutputFormat.setOutputPath(job, new Path(args[1]));
|
|
|
System.exit(job.waitForCompletion(true) ? 0 : 1);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
En este código, lo primero que debemos ver el el String ruta, que indica la ruta donde se encuentra el fichero *cuentas\_valor.txt* que hemos comentado. Hay que cambiar a la ruta correspondiente para su funcionamiento.
|
|
|
|
|
|
Después es de importancia el String[][] empresas que indica lo que se va a buscar en el análisis, según lo ya explicado. Si se quiere probar el mismo análisis, no es necesario modificarlo pero se podría modificar para realizar búsquedas distintas.
|
|
|
|
|
|
Sobre la parte de Hadoop, hay dos partes bien diferenciadas: el Map y el Reduce. El Map se encarga de coger los datos, encontrar la coincidencia y dar el valor, de modo que daría a la salida un montón de pares clave-valor con [Compañía,puntos], pudiendo estar la compañía repetida. El Reducer posteriormente se encargará de coger todos los pares y los reducirá de modo que para cada compañía solo haya una salida con la suma total de puntos obtenidos.
|
|
|
|
|
|
El map, será el encargado de procesar el fichero .csv que exportamos mediante *mongoexport*. Para conocer mejor el contenido de este fichero, se muestra un pequeño fragmento del mismo.
|
|
|
|
|
|
> user,msg
|
|
|
> "DeutscheBank","MT @Lavorgnanomics: #Oil & #gas production is poised to collapse in the months ahead – see http://t.co/BZNi1G34Ir"
|
|
|
> "DeutscheBank","Should we expect dollar strength against the euro and the yen? https://t.co/yQBaSwR5yV #DeAWM @B_Eichengreen"
|
|
|
> "DeutscheBank","RT @DBChampionship: Huge congrats to @PlayTPC (home of the #DBChampionship) for winning the 2014 TPC Network of the Year - Private Clubs! h…"
|
|
|
> "DeutscheBank","Policy Rates Opinion Compendium: Impact on Currencies https://t.co/pFj76tIzOv #DeAWM"
|
|
|
> "DeutscheBank","Clean Energy Investment Jumps 16%, Shaking Off Oil’s Drop http://t.co/cCzNlRqOd6 via @business"
|
|
|
|
|
|
El map irá tomando este fichero línea a línea y separará al encontrar "," el usuario del mensaje. Tomará la primera parte como usuario y el resto como mensaje (para prevenir de que haya "," dentro del mensaje). Después buscará si existe alguna coincidencia con las palabras que teníamos para cada una de las empresas y si la hay se realizará una llamada al método llamado *puntuacion*, que devolverá el número de puntos según lo que lea en el fichero *cuentas\_valor.txt*. Si no se crea el fichero o el usuario no aparece en el mismo, se dará como puntuación '1' por defecto. Una vez obtenida la puntuación, se guardará el nombre de la compañía y los puntos en el contexto que utilizará posteriormente el Reducer que obtendrá los resultados finales.
|
|
|
|
|
|
#### Puesta en marcha
|
|
|
|
|
|
Para poder probar esta parte, lo primero será arrancar el namenode, que gestiona el sistema de ficheros y regula el acceso de los clientes y el datanode, que guarda los bloques en los que se dividen los ficheros (puede haber varios datanodes).
|
|
|
|
|
|
En la carpeta scripts, hay uno llamado ./hadoop_start.sh, que se encarga del arranque de los mismos. Sin embargo, para que funcione hay que realizar algún pequeño cambio:
|
|
|
|
|
|
|
|
|
#!/bin/bash
|
|
|
|
|
|
# -*- ENCODING: UTF-8 -*-
|
|
|
|
|
|
cd
|
|
|
cd cdtools
|
|
|
cd hadoop-2.5.1
|
|
|
bin/hdfs namenode -format
|
|
|
sbin/hadoop-daemon.sh --config /home/teleco/cdtools/hadoop-2.5.1/etc/hadoop/ --hosts localhost --script "bin/hdfs" start namenode
|
|
|
sleep 5
|
|
|
sbin/hadoop-daemon.sh --config /home/teleco/cdtools/hadoop-2.5.1/etc/hadoop/ --hosts localhost --script "bin/hdfs" start datanode
|
|
|
exit
|
|
|
|
|
|
Si la versión de hadoop no es la 2.5.1 o no está en cdtools habrá que indicar donde se encuentra y en el código que arranca el namenode o el datanode habrá que cambiar también la ruta por la correspondiente en la máquina donde se ejecute.
|
|
|
|
|
|
Del mismo modo, una vez que se termine de usar Hadoop, es necesario parar tanto el namenode como el datanode. En scripts también se provee de uno llamado ./hadoop_stop.sh, que se encarga de ello, en el que también habrá que cambiar la ruta de Hadoop por la que le corresponda:
|
|
|
|
|
|
|
|
|
#!/bin/bash
|
|
|
|
|
|
# -*- ENCODING: UTF-8 -*-
|
|
|
|
|
|
cd
|
|
|
cd cdtools
|
|
|
cd hadoop-2.5.1
|
|
|
|
|
|
sbin/hadoop-daemon.sh --config /home/teleco/cdtools/hadoop-2.5.1/etc/hadoop/ --hosts localhost --script "bin/hdfs" stop datanode
|
|
|
sbin/hadoop-daemon.sh --config /home/teleco/cdtools/hadoop-2.5.1/etc/hadoop/ --hosts localhost --script "bin/hdfs" stop namenode
|
|
|
exit
|
|
|
|
|
|
Para poder ejecutar todo el código que realiza el procesamiento de los datos, también se ha creado un script llamado ./hadoop.sh que automatiza todo el proceso. En este script habrá que modificar la ruta en la que se exportan los resultados, en principio, y si hadoop no está en cdtools o no existe el directorio compdist_business_analysis_tweets también habrá que indicar los directorios adecuados.
|
|
|
|
|
|
|
|
|
|
|
|
#!/bin/bash
|
|
|
|
|
|
# -*- ENCODING: UTF-8 -*-
|
|
|
clear
|
|
|
cd
|
|
|
cd compdist_business_analysis_tweets
|
|
|
rm part-r-00000
|
|
|
rm resultados.html
|
|
|
cd
|
|
|
cp compdist_business_analysis_tweets/datos.csv cdtools/hadoop-2.5.1
|
|
|
cd compdist_business_analysis_tweets/hadoop/workspace/WordCount/src
|
|
|
javac -d ../bin -cp ../../../../../cdtools/hadoop-2.5.1/share/hadoop/common/hadoop-common-2.5.1.jar:../../../../../cdtools/hadoop-2.5.1/share/hadoop/mapreduce/hadoop-mapreduce-client-core-2.5.1.jar cdist/WordCount.java
|
|
|
cd ../bin
|
|
|
jar -cf hadoop.jar .
|
|
|
mv hadoop.jar ../../../../../cdtools/hadoop-2.5.1/
|
|
|
|
|
|
cd
|
|
|
cd cdtools
|
|
|
cd hadoop-2.5.1
|
|
|
bin/hdfs dfs -rm -R /prueba
|
|
|
bin/hdfs dfs -mkdir /prueba
|
|
|
bin/hdfs dfs -ls /
|
|
|
bin/hdfs dfs -put datos.csv /prueba/datos.csv
|
|
|
bin/hdfs dfs -ls /prueba
|
|
|
bin/hadoop jar hadoop.jar cdist.WordCount /prueba/datos.csv /prueba/output
|
|
|
bin/hdfs dfs -copyToLocal /prueba/output/part-r-00000 /home/teleco/compdist_business_analysis_tweets/
|
|
|
cd
|
|
|
cd compdist_business_analysis_tweets
|
|
|
cd resultado/MostrarResultados/src
|
|
|
javac Ficheros.java
|
|
|
java Ficheros
|
|
|
cd
|
|
|
cd compdist_business_analysis_tweets
|
|
|
firefox resultados.html
|
|
|
exit
|
|
|
|
|
|
Una vez ejecutado el script, podremos ya obtener los resultados de qué compañía tiene más puntuación según las menciones en tweets. Sin embargo, necesitaremos el último bloque para poder ver dichos resultados.
|
|
|
|
|
|
# BLOQUE III: PRESENTACIÓN DE RESULTADOS EN HTML
|
|
|
-------------------------------------------------- |