Showing posts with label PhantomJS. Show all posts
Showing posts with label PhantomJS. Show all posts

Wednesday, November 05, 2014

Web scrapping con Go y PhatomJS

Hace algún tiempo escribí un blog llamado Web scrapping con Julia y PhantomJS...luego escribí otro blog llamado Web scrapping con Haskell y PhantomJS...

Ahora...es el turno de Go's -;)

El concepto es el mismo...creamos un script en PhantomJS que va a leer la página de Twitter de un usuario y obtener los hashtags de las primeras 5 páginas...aquí está el script en PhantomJS...

Hashtags.js
var system = require('system');

var webpage = require('webpage').create();
webpage.viewportSize = { width: 1280, height: 800 };
webpage.scrollPosition = { top: 0, left: 0 };

var userid = system.args[1];
var profileUrl = "http://www.twitter.com/" + userid;

webpage.open(profileUrl, function(status) {
 if (status === 'fail') {
  console.error('webpage did not open successfully');
  phantom.exit(1);
 }
 var i = 0,
 top,
 queryFn = function() {
  return document.body.scrollHeight;
 };
 setInterval(function() {
  top = webpage.evaluate(queryFn);
  i++;
   
  webpage.scrollPosition = { top: top + 1, left: 0 };

  if (i >= 5) {
   var twitter = webpage.evaluate(function () {
    var twitter = [];
    forEach = Array.prototype.forEach;
    var tweets = document.querySelectorAll('[data-query-source="hashtag_click"]');
    forEach.call(tweets, function(el) {
     twitter.push(el.innerText);
    });
    return twitter;
   });

   twitter.forEach(function(t) {
    console.log(t);
   });

   phantom.exit();
  }
}, 3000);
});

Si ejecutamos el script vamos a ver el siguiente resultado...


Ahora...lo que quiero hacer con esta información...es enviarla a Go...y obtener los hashtags más usados...así que los voy a sumarizar y luego deshacerme de los que no se repiten al menos 5 veces...

Veamos el código en Go...

TwitterHashtags.go
package main

import ( "os/exec"
  "strings" 
  "fmt" )

func main() {
 cmd := exec.Command("phantomjs","--ssl-protocol=any","Hashtags.js", "Blag")
 out, err := cmd.Output()
 if err != nil {
  println(err.Error())
  return
 }
 
 Tweets := strings.Split(string(out), "\n")
 charmap := make(map[string]int)
 for _, value := range Tweets {
  if value != "" {
   charmap[value] += 1
  }
 }
 
 for key, value := range charmap {
  if value >= 5 {
   fmt.Print("(", key, ", ")
   fmt.Println(value, ")")
  }
 }
}

El único problema con este script es que no hay una manera simple y sencilla de ordenar un map[string]int...así que simplemente lo dejo ahí -:)

Aquí está el resultado...


Si alguien conoce alguna manera simple de ordenar esto...por favor avisenme -:)

Saludos,

Blag.
Development Culture.

Tuesday, September 23, 2014

Web Scrapping con Haskell y PhantomJS

Hace un tiempo escribí un blog llamado Web scrapping con Julia y PhantomJS...hoy día...quería hacer lo mismo pero esta vez utilizándo Haskell...

El concepto es el mismo...creamos un script en PhantomJS que va a leer una página de un usuario de Twitter page y obtener los hashtags de las 5 primeras páginas...aquí está el script en PhantomJS...

Hashtags.js
var system = require('system');

var webpage = require('webpage').create();
webpage.viewportSize = { width: 1280, height: 800 };
webpage.scrollPosition = { top: 0, left: 0 };

var userid = system.args[1];
var profileUrl = "http://www.twitter.com/" + userid;

webpage.open(profileUrl, function(status) {
 if (status === 'fail') {
  console.error('webpage did not open successfully');
  phantom.exit(1);
 }
 var i = 0,
 top,
 queryFn = function() {
  return document.body.scrollHeight;
 };
 setInterval(function() {
  top = webpage.evaluate(queryFn);
  i++;
   
  webpage.scrollPosition = { top: top + 1, left: 0 };

  if (i >= 5) {
   var twitter = webpage.evaluate(function () {
    var twitter = [];
    forEach = Array.prototype.forEach;
    var tweets = document.querySelectorAll('[data-query-source="hashtag_click"]');
    forEach.call(tweets, function(el) {
     twitter.push(el.innerText);
    });
    return twitter;
   });

   twitter.forEach(function(t) {
    console.log(t);
   });

   phantom.exit();
  }
}, 3000);
});

Si lo ejecutamos, vamos a ver el siguiente resultado...


Ahora...lo que quiero hacer con esta información...es enviarla a Haskell...y obtener los hashtags más utilizados...así que voy a sumarizar los y luego eliminar los que son menores a 5...

Veamos el código en Haskell...

hashtags.hs
import System.Process
import Data.List

hashTags :: String -> IO()
hashTags(user) = do
 let x = readProcess "phantomjs" ["--ssl-protocol=any","Hashtags.js",user] []
 y <- x
 mapM_ print $ sortBy sortGT $ count y

count :: String -> [(String,Int)]
count xs = filter ((>=5).snd) $ 
     map(\ws -> (head ws, length ws)) $ 
           group $ sort $ words xs

sortGT :: (Ord a, Ord a1) => (a1, a) -> (a1, a) -> Ordering
sortGT (a1, b1) (a2, b2)
  | b1 < b2 = GT
  | b1 > b2 = LT
  | b1 == b2 = compare a1 a2

Si lo ejecutamos, vamos a ver el siguiente resultado


Lo bueno de esta aplicación es que podemos pasar cualquier nombre de usuario como parámetro y el resultado va a estar correctamente ordenado y filtrado...otra razón más para amar Haskell -;)

Saludos,

Blag.
Development Culture.

Wednesday, July 16, 2014

Web Scrapping con Julia y PhantomJS

Como he estado leyendo algunos libros sobre PhantomJS y siempre estoy buscando desarrollar algo interesante en Julia...Pensé que integrarlos podría ser una buena idea -;)

Pensé acerca de Twitter y los hashtags...no sería interesánte escribir un script en PhantomJS para hacer un web scrape en Twitter y obtener todos los hashtags que he usado?

Para este script en particular...Estoy tomando los hashtags de las primeras 5 páginas de Twitter que están enlazadas a mi perfil...

Hashtags.js
var system = require('system');

var webpage = require('webpage').create();
webpage.viewportSize = { width: 1280, height: 800 };
webpage.scrollPosition = { top: 0, left: 0 };

var userid = system.args[1];
var profileUrl = "http://www.twitter.com/" + userid;

webpage.open(profileUrl, function(status) {
 if (status === 'fail') {
  console.error('webpage did not open successfully');
  phantom.exit(1);
 }
 var i = 0,
 top,
 queryFn = function() {
  return document.body.scrollHeight;
 };
 setInterval(function() {
  top = webpage.evaluate(queryFn);
  i++;
   
  webpage.scrollPosition = { top: top + 1, left: 0 };

  if (i >= 5) {
   var twitter = webpage.evaluate(function () {
    var twitter = [];
    forEach = Array.prototype.forEach;
    var tweets = document.querySelectorAll('[data-query-source="hashtag_click"]');
    forEach.call(tweets, function(el) {
     twitter.push(el.innerText);
    });
    return twitter;
   });

   twitter.forEach(function(t) {
    console.log(t);
   });

   phantom.exit();
  }
}, 3000);
});

Si lo ejecutamos...vamos a tener el siguiente resultado...



Ahora...que es lo que quiero hacer con esta información...enviarla a Julia...y obtener los hashtags más usados...así que voy a sumarizarlos y luego deshacerme de los que solo aparecen una vez...

Veamos el código en Julia...


Twitter_Hashtags.jl
tweets = readall(`phantomjs --ssl-protocol=any Hashtags.js Blag`)
tweets = split(tweets,"\n")
hashtags = Dict()
for hash in tweets
 try
  hashtags[hash] += 1
 catch e
  hashtags[hash] = 1
 end
end

filter!((k,v)->v>1,hashtags)

for (k,v) in hashtags
 println("$k has been mentioned $v times")
end

Si lo ejecutamos...vamos a tener el siguiente resultado...


Todavía no se como ordenar diccionarios en Julia...así que tenganme paciencia -:)

En fín...viendo el resultado...podemos tener mis top 3 hashtags -;)

#LeapMotion ==> 14 veces
#Flare3D ==> 11 veces
#DevHangout ==> 8 veces

Espero que les haya gustado y nos vemos la próxima vez -:)

Saludos,

Blag.
Development Culture.

PhantomJS Cookbook - Revew del Libro

Luego de leer y postear acerca de Getting Started with PhantomJS decidí comprar otro libro sobre PhantomJS...por supuesto -;)

Esta vez...conseguí PhantomJS Cookbook...


Este libro es más o menos grande con 304 páginas...y es muy muy bueno...

Por supuesto...siendo un "Cookbook"...siempre hay cosas buenas y cosas malas...las cosas malas son que algunas de las recetas son aburridas o muy obvias (especialmente si ya conoces algo sobre PhantomJS)...y no me malinterpreten...es solo que pienso que si vas a leer un "Cookbook" es porque ya tienes cierto conocimiento y no quieres realmente recibir instrucciones de como realizar las tareas más simples...pero...como siempre...es solo mi opinión...para principiantes...esas recetas deben de ser muy buenas...

Las cosas buenas acerca de este libro...es que las recetas que son buenas...son muy buenas...y las recetas que son impresionantes...son totalmente impresionantes! Estaba realmente muy emocionado y conmicionado por algunas de ellas...

El libro cubre un poco sobre CasperJS, Jasmine, Jenkins y más...mucho más...

Gracias a este libro descubrí lo que es HAR...y como PhantomJS puede ayudarte a generarlo...


Quieren algo sobre Jenkins? Aquí esta -:)


Debo decirlo...si ya compraron "Getting Started with PhantomJS"...deben comprar este "Cookbook"...en serio...es muy bueno -;)

Tomar instantáneas de una páginas utilizándo diferentes tamaños es un script muy bueno también...pero por supuesto no voy a llenar este post con imágenes...puesto que al fín y al cabo...PhantomJS es un browser sin cabeza, no? -;)

Saludos,

Blag.
Development Culture.

Monday, July 14, 2014

Getting Started with PhantomJS - Review del libro

Hace un par de días comencé a leer Getting Started with PhantomJS de Packt Publishing. Ya había oído acerca de PhantomJS en el pasado pero nunca lo había utilizado realmente...así que estaba muy emocionado por leer este libro...


Al igual que todos los libros Getting Started, este es un poco corto...con 140 páginas...pero dejenme que les diga...eso es más que suficiente para mantener tu atención y convertirte en un fanático de PhatomJS -;)

Este libro comienza con una pequeña introducción y luego salta directamente al código...lo cual es algo que yo siempre aprecio -:P

El primer ejemplo importante está basado en Pinterest pero yo no use/no me gusta Pinterest...así que cambié el ejemplo un poco para poder Twitter -;)

Aquí está el código fuente en el que caso de que estén interesados...

var system = require('system');
var userid = system.args[1];
var page = require('webpage').create();

var profileUrl = "http://www.twitter.com/" + userid;
page.open(profileUrl, function(status) {
 if ( status === "success" ) {
  var twitter = page.evaluate(function (uid) {
  var username = document.querySelector('[href="/' + uid + '"]').innerText.trim();
  var numTweets = document.querySelector('[data-nav="tweets"]');
  numTweets = numTweets.attributes[1].value;
  var numFollowing = document.querySelector('[href="/' + uid + '/following"]');
  numFollowing = numFollowing.querySelector('[class="ProfileNav-value"]').innerText;  
  var numFollowers = document.querySelector('[href="/' + uid + '/followers"]');
  numFollowers = numFollowers.querySelector('[class="ProfileNav-value"]').innerText;    
  return {
   name: username,
   tweets: numTweets,
   following: numFollowing,
   followers: numFollowers
         };
}, userid);

console.log(twitter.name + ' (' + userid + ')' + ' has wrote ' + twitter.tweets + ' and has ' +
      twitter.followers + ' followers and is following ' +
      twitter.following + ' accounts ');
}

phantom.exit(0);
});


Y aquí está el resultado...


Interesánte, no? Para ser un simple primer ejemplo...Yo pienso que es impresionante -;)

El libro también viene con ejemplos de como tomar instantaneas de páginas web, performance de carga de páginas web, modificación del DOM, trabajar con archivos y más...

Inclusive incluye una pequeña introducción a CasperJS, la compañía perfecta para PhantomJS.

Debo decir...simplemente vayan y compren este libro...Me encanta! y voy a leer nuevamente solo para poder descubrir y aprender más....PhantomJS es asombroso!

Saludos,

Blag.
Development Culture.