Acceder al interior de un iframe (distinto dominios) con phantomjs

Feb 27, 2013 2 Comments by

Phantomjs es un browser funcional (basado en WebKit) bajo línea de comandos, contiene una API y es programable a través de Javascript, permitiendo manejar (de forma automatizada) Javascript, DOM handling, CSS selector, JSON, Canvas, and SVG realmente en un navegador. Como no requiere de una interfaz X, es ideal para automatiza tareas como pruebas unitarias, captura de pantalla, extracción de datos, etc.

Instalacción

La forma más sencilla es utilizar directamente los binarios precompilados para cada una de las arquitectura disponible (Windows, Linux y OSX) o compilar.
Para Linux, podemos descargar el paquete desde el sitio oficial y descomprimir

wget http://phantomjs.googlecode.com/files/phantomjs-1.8.1-linux-x86_64.tar.bz2
bzip -d phantomjs-1.8.1-linux-x86_64.tar.bz2
tar xvf phantomjs-1.8.1-linux-x86_64.tar.bz2

Para tener acceso al binario desde cualquier punto del sistema, podemos modificar nuestro variable global PATH o crear un enlace al binario de phantomjs

#Suponiendo que hemos descomprimido en opt
ln /opt/phantomjs/phantomjs-1.8.1-linux-x86_64/bin/phantomjs /usr/bin/ -s

Ejemplo

La carpeta examples, contiene una decente lista de script de ejemplos de diversas tareas, por ejemplo podemos correr el script que imprime el tiempo de carga de un sitio web.

phantomjs loadspeed.js http://deerme.org
#Page title is deerme
#Loading time 3145 msec

El código fuente habla por si solo.

var page = require('webpage').create(),
    system = require('system'),
    t, address;

if (system.args.length === 1) {
    console.log('Usage: loadspeed.js <some URL>');
    phantom.exit(1);
} else {
    t = Date.now();
    address = system.args[1];
    page.open(address, function (status) {
        if (status !== 'success') {
            console.log('FAIL to load the address');
        } else {
            t = Date.now() - t;
            console.log('Page title is ' + page.evaluate(function () {
                return document.title;
            }));
            console.log('Loading time ' + t + ' msec');
        }
        phantom.exit();
    });
}

Accediendo al interior de un Iframe

Por politica de seguridad, los script de distintos dominios no pueden intercambiar información entre el documento principal y el iframe, existen ciertas técnicas que permite “comunicar” como jsonp, pero el manejo de dom, ejecución de scripts, etc. no es posible. Sin embargo, phantomjs contiene la opción web-security donde podemos hacer caso omiso a las politicas tradicionales :) .

El script carga la página, verifica que exista jQuery (si no, lo carga), y comienza a acceder al primer iframe (ejemplo #aswift_2), el segundo (#google_ads_frame3) y finalmente obtenemos algún dato del último enlace.

/*
	Accessing an iframe (different domain) with phantomfs
	Example for deerme.org
*/

var page = require('webpage').create(), system = require('system'), t, address;
if (system.args.length === 1)
{
	console.log('Usage: phantomfs iframe.js <some URL>');
	phantom.exit();
}

t = Date.now();
address = system.args[1];
page.open(address, function (status)
{
	if (status !== 'success')
	{
        	console.log('FAIL to load the address');
	}
	else
	{
        	t = (Date.now()) - t;
		title = page.evaluate( function(){
			return document.title;
		});
		linkTitle = page.evaluate( function(){
			// The site containing jQuery?
			if ( typeof(jQuery) == "undefined" )
			{
				// Force Load
				page.injectJs('http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js');
			}
			// first iframe #aswift_2
			// second iframe #google_ads_frame3
			return jQuery("#aswift_2").contents()
				.find("body")
					.find("#google_ads_frame3")
						.contents()
							.find("body")
								.contents()
									.find("a:last")
										.attr("title");
		});
		console.log('Loading time: ' + t + ' msec');
		console.log('Webpage title: ' + title);
		console.log('Link title (iframe adsense): ' + linkTitle);
	}
	phantom.exit();
});

Procedemos a ejecutar el script (debemos indicar la opción –web-security=no)

phantomjs --web-security=no iframe.js http://deerme.org
#Loading time: 4525 msec
#Webpage title: deerme
#Link title (iframe adsense): www.axia.cl
Javascript, Web Scraping

About the author

Ingeniero en Informática, Oracle Certified Master Java EE 6 Enterprise Architect, Oracle Certified Professional Java Programmer. Experto en distintas ramas de la computación y otras "yerbas" xD. Si te gusto este post, sígueme en @deerme_org, escríbeme a info AT deerme.org o contactame por linkedin.

2 Responses to “Acceder al interior de un iframe (distinto dominios) con phantomjs”

  1. Daniel Pizarro says:

    excelente, muchisimas gracias. solo con este codigo se pueden hacer muchas mas cosas que con otros softwares de elevado precio y que no ayudan tanto.
    mi codigo quedo asi y deja toda la informacion que buscaba en un archivo de texto

    /*
    Accessing an iframe (different domain) with phantomfs
    Example for deerme.org
    */

    var page = require(‘webpage’).create(), system = require(‘system’), t, address;
    if (system.args.length === 1)
    {
    console.log(‘Usage: phantomfs iframe.js ‘);
    phantom.exit();
    }

    t = Date.now();
    address = system.args[1];
    page.open(address, function (status)
    {
    if (status !== ‘success’)
    {
    console.log(‘FAIL to load the address’);
    }
    else
    {
    t = (Date.now()) – t;

    var ua = page.evaluate(function() {
    return document.getElementById(‘content-main’).innerHTML;
    });
    var numero = ua.length;
    if (numero < 500)
    {
    var ua = page.evaluate(function() {
    return document.getElementById('content-main').innerHTML;
    });
    }
    var fs = require('fs');
    var path = '/data/dividendos.txt';
    fs.write(path, ua, 'w');
    console.log(ua);
    }
    phantom.exit();
    });

  2. deerme.org says:

    Gracias Daniel por tu comentario. Efectivamente, phantomjs es un proyecto muy interesante para muchas áreas

Leave a Reply


+ nine = 14