Hacking around
Menu
Skip to content
Post navigation
← Periodismo canino
Espiando por deporte cámaras de videovigilancia →
Web scraping a pelo desde la shell in the night
by Fanta
1. ¿Qué es el web scraping?
2. ¿Para que se usa esto?
3. ¿Que herramientas vamos a usar hoy?
4. Ejemplo practico 0. Scrapear listado de proxies para aplicarlos en nuestro script de scrapeo
—
1. ¿Qué cojones demonios es el web scraping?
Básicamente el “Web Scraping” es una técnica utilizada por software para extraer información de
sitios webs.
Normalmente los programas que utilizan esta técnica simulan la navegación de un humano en la
web.
Nosotras llamamos a estos programas muchas veces “bots” ya que nos automatizan la tarea de
recopilar datos de determinadas webs y trabajan para nosotros mientras dormimos.
2. ¿Para que se usa esto?
Pues para muchisimas cosas.
Por ejemplo para comparar precios en determinadas tiendas. Obtienes los precios de los productos
de una tienda virtual y los comparas con los que obtienes de otras y consigues determinar
probablemente cual es el más barato.
También por ejemplo como con el caso de dipubot para mostrar en [Link] y twitter los resultados
de las votaciones en el congreso.
Para obtener los emails de los diputados y sus cuentas de twitter y poder hacer herramientas como
[Link]
3. ¿Que herramientas vamos a usar hoy?
Normalmente con 10 herramientas o menos será suficiente para scrapear una web.
Hoy vamos a usar bash. Normalmente encontraremos bash en casi cualquier distro de linux.
Las herramientas que vamos a usar son básicamente las GNU core utils y algunas otras.
Lo que pretendemos es simular lo que visita un humano cuando navega por la web, es decir, vamos
a visitar las webs como lo hacemos normalmente pero en vez de usar un navegador web que haga
esas peticiones web lo que vamos a usar es wget y en vez de ver la web como la interpretaría un
navegador lo que hacemos es descargarla sin interpretarla.
Las herramientas que vamos a usar hoy son muy pocas y son estas:
wget – Para descargar webs.
curl – Para descargar webs rellenando formularios
tr – Para traducir o borrar caracteres
grep – Para filtrar por determinados caracteres o inversamente.
cut – Para cortar por determinados delimitadores.
head tail – Para cortar por lineas.
sort – Para ordenar.
uniq – Para filtrar sacando solamente resultados idénticos.
cat – Para imprimir por pantalla o salida standard un archivo
echo – Para imprimir por pantalla o salida standard una cadena o el contenido de una variable.
wc - Para contar caracteres o lineas por ejemplo.
sleep – Sirve para parar unos segundos (por ejemplo) la ejecución de un script (por ejemplo).
Con eso ya podemos scrapear la web del congreso de los diputados, el BORME, el BOE y cualquier
web que podamos imaginar siempre y cuando no usen javascript para mostrar los datos.
Necesitaremos por tanto Firefox como navegador (también vale iceweasel y otros) ya que nos
permite visitar una web y seleccionar una parte determina de esta para posteriormente ver solamente
esa parte del código y no toda.
Necesitaremos una shell con las herramientas citadas antes. Empezamos. Vamos a ver algún
ejemplo de estas herramientas.
wget – Para descargar webs.
wget “[Link]
Eso nos muestra por pantalla datos que en un script no queremos que se muestren y aparte guarda lo
que queremos descargar (la web de la wikipedia) como: Jose_Luis_Rodriguez_Zapatero y no como
nosotras quisiéramos.
Para ocultar por tanto que no se vean los datos de descarga usaremos -q
wget -q “[Link]
Ya no veremos nada raro por pantalla pero se descargará igualmente el tema.
Para que se guarde con el nombre que queramos darle usaremos -O
wget -q “[Link] -O zapatero
Eso nos guarda la web con el nombre zapatero y después podemos mostrar por pantalla todo el
código de esa web usando por ejemplo el programa cat.
Más tarde hablaremos de más opciones de wget ya que tiene muchas. Con saber estas de momento
nos vale.
cat – Para imprimir por pantalla o salida standard un archivo
Hemos descargado el contenido de la página en wikipedia referente a Zapatero y la hemos
descargado a un archivo llamado zapatero.
Vamos a mostrar por pantalla el contenido del archivo zapatero así:
cat zapatero
wc -l – Para contar
cat por defecto al igual que muchos programas de linea de comandos mostrará en pantalla el
contenido del archivo que le indiquemos pero si redireccionamos ese contenido podremos metérselo
a la entrada de otro programa como por ejemplo wc.
Ejemplo:
cat zapatero | wc -l
Nos cuenta las lineas que tiene ese documento.
grep – Para filtrar por determinados caracteres o inversamente.
Antes de usar grep hemos de visualizar la web o el contenido que hemos descargado en el archivo
zapatero. A mi me gusta usar firefox por el tema de que puedes seleccionar y darle clic derecho a
ver código y de ese modo simplemente ves esa parte que te interesa pero … supongo que otras
personas usáis firebug u otros navegadores.
Queremos sacar la fecha de nacimiento y es por eso que en la web vamos a ver ese código en
especial.
<tr>
<td style="font-weight:bold">Nacimiento</td>
<td><a href="/wiki/4_de_agosto" title="4 de agosto">4 de agosto</a> de <a
href="/wiki/1960" title="1960">1960</a> (52 años)<br>
<a href="/wiki/Valladolid" title="Valladolid">Valladolid</a>, <a
href="/wiki/Espa%C3%B1a" title="España">España</a></td>
</tr>
cat zapatero | grep “title=” | grep “años” | grep “/wiki/” | grep “td”
<td><a href=”/wiki/4_de_agosto” title=”4 de agosto”>4 de agosto</a> de <a href=”/wiki/1960″
title=”1960″>1960</a> (52 años)<br />
cut – Para cortar por determinados delimitadores.
Es hora de recortar esa linea que tenemos para sacar solamente los datos que queremos de ella.
Para ello nos fijamos en si existe algún carácter que podamos usar de delimitador. En este caso
existe (y suele ser casi siempre ese en todas las webs) y es “>” y “<”.
cat zapatero | grep “title=” | grep “años” | grep “/wiki/” | grep “td” | cut -d “>” -f3-5
4 de agosto</a> de <a href=”/wiki/1960″ title=”1960″>1960</a
Sigue sin estar muy limpio por lo que vamos a seguir cortando:
cat zapatero | grep “title=” | grep “años” | grep “/wiki/” | grep “td” | cut -d “>” -f3-5 | cut -d “<” -f1,3
4 de agosto<a href=”/wiki/1960″ title=”1960″>1960
cat zapatero | grep “title=” | grep “años” | grep “/wiki/” | grep “td” | cut -d “>” -f3-5 | cut -d “<” -f1
Eso nos saca: 4 de agosto
El año lo podríamos sacar así:
cat zapatero | grep “title=” | grep “años” | grep “/wiki/” | grep “td” | cut -d “>” -f3-5 | cut -d “>” -f3 |
cut -d “<” -f1
1960
Tenemos por tanto 2 lineas. Una que nos saca el día y el mes y otra el año y por tanto vamos a
volcar esas lineas a 2 variables. Una llamada $diames y otra llamada $ano
diames=`cat zapatero | grep “title=” | grep “años” | grep “/wiki/” | grep “td” | cut -d “>” -f3-5 | cut -d
“<” -f1`
ano=`cat zapatero | grep “title=” | grep “años” | grep “/wiki/” | grep “td” | cut -d “>” -f3-5 | cut -d
“>” -f3 | cut -d “<” -f1`
echo – Para imprimir por pantalla o salida standard una cadena o el contenido de una variable.
Ahora con echo vamos a mostrar el contenido de ambas variables para tener la fecha bien
controlada. Podríamos incluso volcar esto todo junto a una nueva variable.
echo “$diames de $ano”
4 de agosto de 1960
fecha=`echo “$diames de $ano”`
echo $fecha
4 de agosto de 1960
Ya tenemos por tanto la fecha de nacimiento de Zapatero extraída de su web en wikipedia.
Si quisiéramos tener la de otros políticos que tengan web en wikipedia tendríamos simplemente que
cambiar la url inicial en la que descargamos todo el tinglado.
Esto es un ejemplo un poco tonto solamente para darle uso a estas herramientas. Ahora veremos ya
un ejemplo más chulo y de utilidad.
4. Ejemplo practico 0. Scrapear listado de proxies para aplicarlos en nuestro script de scrapeo
El ejemplo anterior era un poco tonto pero lo mismo sirve un poco para ir viendo las utilidades.
Cuando queremos scrapear una web los administradores suelen poner determinados impedimentos
para que sus webs no sean tan copiables o para simplemente tratar de mantener el servicio activo
para los humanos y menos activo para lo que detectan que son peticiones no usuales.
Si una web por ejemplo tiene 1000 peticiones en un minuto eso es raro que pueda hacerlo un
humano dándole a la tecla F5 y es por eso que si queremos saltarnos esas limitaciones que nos
ponen vamos a tener que actuar como si fuésemos humanos.
Algunas restricciones que nos ponen pueden ser de estos tipos:
Bloquean acceso cuando tienen muchas peticiones seguidas desde una misma IP.
Bloquean acceso por headers, es decir, la información que deja nuestro navegador al visitar
una web.
Con este script vamos a ver como saltarnos ambas restricciones con un ejemplo real y practico.
En la siguiente web: [Link] ofrecen un listado de proxys, es decir, de direcciones de
ordenadores que ofrecen servicio de proxy de modo que si lo configurásemos en nuestro navegador
podríamos visitar las webs dejando la IP de otro ordenador en vez de la nuestra.
El problema de esa web es que si la visitamos con wget a pelo no nos descarga nada.
wget “[Link]”
–2013-03-05 15:10:10– [Link]
Resolving [Link]… [Link]
Connecting to [Link]|[Link]|:80… connected.
HTTP request sent, awaiting response… 403 Forbidden
2013-03-05 15:10:10 ERROR 403: Forbidden.
Al usar wget sin la opción -q veremos que en la salida nos indica que el server nos esta mostrando
un error 403 de Prohibido pero que si visitamos la web en vez de con wget con por ejemplo un
navegador web como firefox o midory veremos que si que se carga la web.
Esto ocurre porque el admin es un listo y tiene bloqueado el acceso a wget con la finalidad que a el
le de la gana. Lo hace ya que wget envía una serie de headers cuando pide la web, es decir, cuando
le indicamos que conecte. Wget al igual que un navegador envía una serie de datos y es por tanto
que en el servidor si no les gustan pueden bloquear.
Para ver que ip tenemos actualmente y que navegador estamos usando (que datos estamos enviando
en los headers) podemos visitar esta web:
[Link]
Si la visitamos con firefox lo mismo tenemos algo como esto:
[Link]
Mozilla/5.0 (X11; Linux i686 on x86_64; rv:19.0) Gecko/20100101 Firefox/19.0
Si la visitamos con wget desde consola:
wget -q “[Link] -O – | more
Obtenemos algo como esto otro:
[Link]
Wget/1.12 (linux-gnu)
De esa forma vemos que los datos que enviamos cuando visitamos una web con wget son
precisamente que estamos usando wget e incluso desde que sistema operativo.
Lo tienen fácil en [Link] por tanto para no dejarnos pasar si navegamos con wget.
Lo bueno es que wget permite, al igual que muchos navegadores como midori (de forma muy
sencilla), cambiar esos datos por otros y simular por tanto que navegamos desde por ejemplo
Internet explorer cuando realmente estamos haciendo las peticiones desde wget.
wget –user-agent=”Internet explorer 2.0″ “[Link] -O – | cat
Ahora si que entramos y wget no nos saca el error 403 de antes.
Podemos añadir más headers como estos:
–header=”Keep-Alive: 300″
–referer=”[Link]
De forma que estamos indicando que hemos llegado a esa web desde la web de la sgae y todas las
peticiones que hagamos vendrán como si las hiciéramos desde la web de la sgae ya que se supone
tienen un enlace allí (aunque no es cierto).
Con esta linea por ejemplo sacaríamos un listado:
wget -q –no-proxy –user-agent=”Internet explorer 2.0″ –header=”Keep-Alive: 300″ –
referer=”[Link] “[Link] -O – | grep “spy14>” | tr “>” “n”
| grep “</font” | grep “:” | grep -v “-” | cut -d “<” -f1
[Link]:3128
[Link]:3129
[Link]:8080
[Link]:80
[Link]:8080
[Link]:3128
[Link]:80
[Link]:8080
[Link]:80
[Link]:3128
[Link]:80
[Link]:3128
[Link]:8080
[Link]:8080
[Link]:8080
[Link]:3128
[Link]:8080
[Link]:3128
Si le añadimos un head -1 al final solamente pillaríamos uno en un momento dado:
wget -q –no-proxy –user-agent=”Internet explorer 2.0″ –header=”Keep-Alive: 300″ –
referer=”[Link] “[Link] -O – | grep “spy14>” | tr “>” “n”
| grep “</font” | grep “:” | grep -v “-” | cut -d “<” -f1 | head -1
[Link]:3128
Podemos volcarlo a variable y exportarlo para que wget lo pille por defecto, es decir, pille por
defecto el proxy y lo use.
proxy=`wget -q –no-proxy –user-agent=”Internet explorer 2.0″ –header=”Keep-Alive: 300″ –
referer=”[Link] “[Link] -O – | grep “spy14>” | tr “>” “n”
| grep “</font” | grep “:” | grep -v “-” | cut -d “<” -f1 | head -1`
echo “Usando $proxy con wget”
export http_proxy=$proxy