¿Cuál es la mejor forma de extraer datos de un sitio web? [cerrado]

107

Necesito extraer contenido de un sitio web, pero la aplicación no proporciona ninguna interfaz de programación de aplicaciones u otro mecanismo para acceder a esos datos mediante programación.

Encontré una herramienta de terceros útil llamada Import.io que proporciona la funcionalidad de hacer clic e ir para raspar páginas web y crear conjuntos de datos, lo único que quiero es mantener mis datos localmente y no quiero suscribirme a ningún plan de suscripción. .

¿Qué tipo de técnica utiliza esta empresa para raspar las páginas web y construir sus conjuntos de datos? Encontré algunos marcos de raspado web pjscrape & Scrapy, ¿ podrían proporcionar esa característica?

0x1ad2
fuente
4
PHP ciertamente no está fuera de discusión, eso es simplemente incorrecto, obviamente. gist.github.com/krakjoe/b1526fcc828621e840cb
Joe Watkins
@JoeWatkins que se ve realmente genial, ¿necesita una configuración especial de PHP para ejecutarse? ¿Y cómo es el rendimiento en comparación con las herramientas / lenguajes que se proporcionan a continuación?
0x1ad2
1
Requiere una compilación segura para subprocesos de PHP y pthreads, lea github.com/krakjoe/pthreads/blob/master/README.md , puede encontrarme en el chat si quiere ayuda, yo o cualquier otra persona :)
Joe Watkins
@ 0x1ad2 Si desea mantener los datos localmente, debería probar el software ( datascraping.co ) en lugar de las API web. La mayoría de las herramientas utilizan Xpath, selector CSS y REGEX para extraer los datos de sitios web y Data Scraping Studio admite todas estas 3 funciones.
Vikash Rathee
Hay dos formas, una es implementar la suya propia utilizando bibliotecas de código abierto / gratuitas, lo que requiere mucho esfuerzo. Literalmente, puede generar un rastreador web ajax para cualquier sitio usando scrape.it. Es una herramienta paga, pero funcionó cuando ninguna de las herramientas gratuitas como import.io o kimono podían renderizar.
Amo Python

Respuestas:

271

Definitivamente querrás comenzar con un buen marco de web scraping. Más adelante, puede decidir que son demasiado limitantes y puede armar su propia pila de bibliotecas, pero sin mucha experiencia en scraping, su diseño será mucho peor que pjscrape o scrapy.

Nota: Utilizo los términos rastreo y raspado básicamente intercambiables aquí. Esta es una copia de mi respuesta a tu pregunta de Quora, es bastante larga.

Herramientas

Familiarícese con las herramientas de desarrollo de Firebug o Chrome, según su navegador preferido. Esto será absolutamente necesario mientras navega por el sitio del que está extrayendo datos y mapea qué URL contienen los datos que está buscando y qué formatos de datos componen las respuestas.

Necesitará un buen conocimiento práctico de HTTP y HTML y probablemente querrá encontrar una pieza decente en el software de proxy intermedio. Deberá poder inspeccionar las solicitudes y respuestas HTTP y comprender cómo se transmiten las cookies y la información de la sesión y los parámetros de consulta. Fiddler ( http://www.telerik.com/fiddler ) y Charles Proxy ( http://www.charlesproxy.com/ ) son herramientas populares. Uso mucho mitmproxy ( http://mitmproxy.org/ ) porque soy más un tipo de teclado que de ratón.

Algún tipo de entorno de tipo consola / shell / REPL donde pueda probar varios fragmentos de código con comentarios instantáneos será invaluable. Las tareas de ingeniería inversa como esta son muchas pruebas y errores, por lo que querrá un flujo de trabajo que lo haga fácil.

Idioma

PHP está básicamente descatalogado, no es adecuado para esta tarea y el soporte de la biblioteca / marco es deficiente en esta área. Python (Scrapy es un excelente punto de partida) y Clojure / Clojurescript (increíblemente poderoso y productivo pero con una gran curva de aprendizaje) son excelentes lenguajes para este problema. Dado que prefiere no aprender un nuevo idioma y ya conoce Javascript, definitivamente sugeriría que se quede con JS. No he usado pjscrape pero se ve bastante bien después de una lectura rápida de sus documentos. Es muy adecuado e implementa una excelente solución al problema que describo a continuación.

Una nota sobre las expresiones regulares: NO USE EXPRESIONES REGULARES PARA PARAR HTML. Muchos principiantes hacen esto porque ya están familiarizados con las expresiones regulares. Es un gran error, use los selectores xpath o css para navegar html y solo use expresiones regulares para extraer datos del texto real dentro de un nodo html. Es posible que esto ya sea obvio para usted, se vuelve obvio rápidamente si lo intenta, pero mucha gente pierde mucho tiempo yendo por este camino por alguna razón. No tenga miedo de los selectores xpath o css, son MUCHO más fáciles de aprender que las expresiones regulares y fueron diseñados para resolver este problema exacto.

Sitios con mucho Javascript

En los viejos tiempos, solo tenía que hacer una solicitud http y analizar la respuesta HTML. Ahora es casi seguro que tendrá que lidiar con sitios que son una combinación de solicitudes / respuestas HTTP HTML estándar y llamadas HTTP asíncronas realizadas por la parte javascript del sitio de destino. Aquí es donde su software proxy y la pestaña de red de firebug / devtools resultan muy útiles. Las respuestas a estos pueden ser html o json, en casos raros serán xml u otra cosa.

Hay dos enfoques para este problema:

El enfoque de bajo nivel:

Puede averiguar qué URL ajax está llamando el sitio javascript y cómo se ven esas respuestas y hacer esas mismas solicitudes usted mismo. Por lo tanto, puede extraer el html de http://example.com/foobar y extraer una pieza de datos y luego tener que extraer la respuesta json de http://example.com/api/baz?foo=b ... para obtener el otro dato. Deberá saber pasar las cookies o los parámetros de sesión correctos. Es muy raro, pero ocasionalmente algunos parámetros requeridos para una llamada ajax serán el resultado de algún cálculo loco realizado en el javascript del sitio, la ingeniería inversa puede ser molesta.

El enfoque del navegador integrado:

¿Por qué necesita averiguar qué datos están en html y qué datos provienen de una llamada ajax? ¿Gestionar toda esa sesión y datos de cookies? No tiene que hacerlo cuando navega por un sitio, el navegador y el sitio javascript lo hacen. Ese es todo el punto.

Si simplemente carga la página en un motor de navegador sin cabeza como phantomjs, cargará la página, ejecutará el javascript y le dirá cuando se hayan completado todas las llamadas ajax. Puede inyectar su propio javascript si es necesario para activar los clics apropiados o lo que sea necesario para activar el javascript del sitio para cargar los datos apropiados.

Ahora tiene dos opciones, hacer que escupe el html terminado y analizarlo o inyectar algo de javascript en la página que realiza el análisis y el formato de datos y escupe los datos (probablemente en formato json). También puede mezclar libremente estas dos opciones.

¿Qué enfoque es el mejor?

Eso depende, seguramente tendrá que estar familiarizado y cómodo con el enfoque de bajo nivel. El enfoque del navegador integrado funciona para cualquier cosa, será mucho más fácil de implementar y hará que desaparezcan algunos de los problemas más complicados de scraping. También es una pieza de maquinaria bastante compleja que deberá comprender. No son solo solicitudes y respuestas HTTP, son solicitudes, renderizado del navegador integrado, javascript del sitio, javascript inyectado, su propio código e interacción bidireccional con el proceso del navegador integrado.

El navegador incrustado también es mucho más lento a escala debido a la sobrecarga de procesamiento, pero eso casi seguramente no importará a menos que esté raspando muchos dominios diferentes. Su necesidad de limitar la tasa de sus solicitudes hará que el tiempo de procesamiento sea completamente insignificante en el caso de un solo dominio.

Limitación de velocidad / comportamiento del bot

Debes estar muy consciente de esto. Debe realizar solicitudes a sus dominios de destino a un ritmo razonable. Necesita escribir un bot que se comporte bien al rastrear sitios web, y eso significa respetar el archivo robots.txt y no golpear el servidor con solicitudes. Los errores o la negligencia aquí son muy poco éticos, ya que esto puede considerarse un ataque de denegación de servicio. La tasa aceptable varía según a quién le pregunte, 1req / s es el máximo al que se ejecuta el rastreador de Google, pero usted no es Google y probablemente no sea tan bienvenido como Google. Mantenlo tan lento como sea razonable. Sugeriría 2-5 segundos entre cada solicitud de página.

Identifique sus solicitudes con una cadena de agente de usuario que identifique su bot y tenga una página web para su bot que explique su propósito. Esta URL va en la cadena del agente.

Será fácil bloquearlo si el sitio quiere bloquearlo. Un ingeniero inteligente por su parte puede identificar fácilmente los bots y unos minutos de trabajo por su parte pueden causar semanas de trabajo cambiando su código de raspado por su parte o simplemente hacerlo imposible. Si la relación es antagónica, un ingeniero inteligente en el sitio de destino puede obstaculizar por completo a un ingeniero genio que escribe un rastreador. El raspado de código es intrínsecamente frágil y esto se explota fácilmente. Algo que provocaría esta respuesta es casi seguro que no es ético de todos modos, así que escriba un bot que se porta bien y no se preocupe por esto.

Pruebas

¿No eres un examinador de unidad / integración? Demasiado. Ahora tendrás que convertirte en uno. Los sitios cambian con frecuencia y cambiará su código con frecuencia. Ésta es una gran parte del desafío.

Hay muchas partes móviles involucradas en el raspado de un sitio web moderno, las buenas prácticas de prueba ayudarán mucho. Muchos de los errores que encontrará al escribir este tipo de código serán del tipo que devuelve datos corruptos de forma silenciosa. Sin buenas pruebas para verificar las regresiones, descubrirá que ha estado guardando datos corruptos inútiles en su base de datos durante un tiempo sin darse cuenta. Este proyecto lo familiarizará mucho con la validación de datos (encontrará algunas buenas bibliotecas para usar) y las pruebas. No hay muchos otros problemas que combinen requiriendo pruebas exhaustivas y sean muy difíciles de probar.

La segunda parte de sus pruebas implica el almacenamiento en caché y la detección de cambios. Mientras escribe su código, no desea martillar el servidor para la misma página una y otra vez sin ningún motivo. Mientras ejecuta sus pruebas unitarias, desea saber si sus pruebas fallan porque rompió su código o porque el sitio web ha sido rediseñado. Ejecute sus pruebas unitarias contra una copia en caché de las URL involucradas. Un proxy de almacenamiento en caché es muy útil aquí, pero es complicado de configurar y usar correctamente.

También desea saber si el sitio ha cambiado. Si rediseñaron el sitio y su rastreador no funciona, sus pruebas unitarias aún se aprobarán porque se ejecutan en una copia en caché. Necesitará otro conjunto más pequeño de pruebas de integración que se ejecutan con poca frecuencia en el sitio en vivo o un buen registro y detección de errores en su código de rastreo que registra los problemas exactos, lo alerta sobre el problema y detiene el rastreo. Ahora puede actualizar su caché, ejecutar sus pruebas unitarias y ver qué necesita cambiar.

Asuntos legales

La ley aquí puede ser un poco peligrosa si haces cosas estúpidas. Si la ley se involucra, se trata de personas que normalmente se refieren a wget y curl como "herramientas de piratería". No quieres esto.

La realidad ética de la situación es que no hay diferencia entre usar un software de navegador para solicitar una URL y ver algunos datos y usar su propio software para solicitar una URL y ver algunos datos. Google es la empresa de raspado más grande del mundo y son amados por ello. Identificar el nombre de su bots en el agente de usuario y ser abierto sobre los objetivos e intenciones de su rastreador web ayudará aquí, ya que la ley entiende qué es Google. Si está haciendo algo sospechoso, como crear cuentas de usuario falsas o acceder a áreas del sitio que no debería (ya sea "bloqueado" por robots.txt o debido a algún tipo de explotación de autorización), entonces tenga en cuenta que está haciendo algo poco ético. y la ignorancia tecnológica de la ley será extraordinariamente peligrosa aquí. Es una situación ridícula, pero es real.

Es literalmente posible intentar construir un nuevo motor de búsqueda como un ciudadano honrado, cometer un error o tener un error en su software y ser visto como un hacker. No es algo que quieras considerando la realidad política actual.

¿Quién soy yo para escribir esta pared gigante de texto de todos modos?

He escrito mucho código relacionado con el rastreo web en mi vida. He estado desarrollando software relacionado con la web durante más de una década como consultor, empleado y fundador de una startup. Los primeros días estaban escribiendo rastreadores / raspadores de perl y sitios web php. Cuando estábamos incrustando iframes ocultos cargando datos csv en páginas web para hacer ajax antes de que Jesse James Garrett lo llamara ajax, antes de que XMLHTTPRequest fuera una idea. Antes de jQuery, antes de json. Tengo alrededor de 30 años, eso aparentemente se considera antiguo para este negocio.

He escrito dos veces sistemas de rastreo / rastreo a gran escala, una vez para un equipo grande en una empresa de medios (en Perl) y recientemente para un equipo pequeño como CTO de una startup de motores de búsqueda (en Python / Javascript). Actualmente trabajo como consultor, principalmente codificando en Clojure / Clojurescript (un maravilloso lenguaje experto en general y tiene bibliotecas que hacen que los problemas de rastreadores / raspadores sean una delicia)

También he escrito exitosos sistemas de software anti-rastreo. Es muy fácil escribir sitios casi imposibles de rastrear si lo desea o identificar y sabotear los bots que no le gustan.

Me gusta escribir rastreadores, raspadores y analizadores más que cualquier otro tipo de software. Es desafiante, divertido y puede usarse para crear cosas asombrosas.

Jesse Sherlock
fuente
4
Solía ​​estar de acuerdo contigo en que PHP es una mala elección, pero con las bibliotecas adecuadas no es tan malo. La manipulación de expresiones regulares y de matriz / picadura es torpe, pero en el lado positivo es rápida y en todas partes.
pguardiario
3
En un entorno donde hay unas pocas bibliotecas que hacen que esto sea un placer y muchas que lo hacen bastante simple y bastante fácil ... ¿por qué te conformarías con "no tan mal"? Estoy de acuerdo, es factible en PHP (y FORTRAN, C, VB, etc.) pero a menos que su problema sea realmente muy simple, sería una idea mucho mejor utilizar las herramientas adecuadas para el trabajo. Y nuevamente, a menos que tenga un problema increíblemente simple que resolver ... ¿qué importa que la expresión regular esté en todas partes? La instalación de bibliotecas es mucho más simple que casi todos los problemas de raspado. Y, de hecho, la expresión regular suele ser bastante lenta para este problema.
Jesse Sherlock
5
Puede que tengas razón, pero sé con certeza que no puedo hacerlo tan fácilmente en PHP. Antes de dejar PHP, tenía casi una década de experiencia profesional en PHP. Pasé más de un año a tiempo completo construyendo un sistema de scraping a escala, en Python, y no puedo imaginarme prescindir de algunas de las bonitas bibliotecas que no están disponibles en PHP o prescindir de las concisas técnicas de metaprogramación disponibles en Python. . Esa es también la razón por la que me mudé a Clojure, para obtener capacidades de metaprogramación aún más poderosas.
Jesse Sherlock
4
Enlive, junto con el poder de Clojure para el código específico del proyecto, son los mayores ganadores. Schema es una gran biblioteca de validación, que es una parte muy importante del código de extracción de información. Actualmente estoy muy contento con la fácil interoperabilidad con el mundo Java para cosas como Mahout, así como Nashorn / Rhino para algunos tipos de ejecución js. Y la gente de Clojure es del tipo que escribe bibliotecas como esta github.com/shriphani/subotai para que usted no tenga que hacerlo. ... continúa en el siguiente comentario ...
Jesse Sherlock
3
También descubrí que cuando realmente necesitas un navegador real y necesitas ir con phantomjs / casperjs, es realmente genial usar clojurescript (a menudo código compartido entre clj y cljs usando cljx) para escribir los js que inyectas en la página en lugar de clojurescript . Core.async es excelente para coordinar código de rastreo altamente concurrente en el servidor, así como para salir del infierno de devolución de llamada dentro del entorno js (coordinar la automatización del navegador con el código cljs core.async dentro de phantomjs es un paraíso en comparación con las alternativas).
Jesse Sherlock
21

Sí, puedes hacerlo tú mismo. Es solo cuestión de tomar las fuentes de la página y analizarlas de la manera que desee.

Hay varias posibilidades. Un buen combo es usar solicitudes de python (construido sobre urllib2, está urllib.requesten Python3) y BeautifulSoup4 , que tiene sus métodos para seleccionar elementos y también permite selectores CSS :

import requests
from BeautifulSoup4 import BeautifulSoup as bs
request = requests.get("http://foo.bar")
soup = bs(request.text) 
some_elements = soup.find_all("div", class_="myCssClass")

Algunos preferirán el análisis de xpath o pyquery como jquery, lxml o algo más .

Cuando los datos que desea son producidos por JavaScript , lo anterior no funcionará. Necesitas python-ghost o Selenium. Prefiero este último combinado con PhantomJS , mucho más ligero y sencillo de instalar y fácil de usar:

from selenium import webdriver
client = webdriver.PhantomJS()
client.get("http://foo")
soup = bs(client.page_source)

Le aconsejo que comience su propia solución. Comprenderá los beneficios de Scrapy al hacerlo.

ps: eche un vistazo a scrapely: https://github.com/scrapy/scrapely

pps: echa un vistazo a Portia, para empezar a extraer información visualmente, sin conocimientos de programación: https://github.com/scrapinghub/portia

Ehvince
fuente
Muy bien, gracias por la respuesta, el único problema es que Python no está en mi conjunto de habilidades. ¿Existen otros buenos lenguajes de programación que puedan realizar las mismas tareas? Principalmente trabajo con PHP y Javascript.
0x1ad2
Perdón por la confusión (mencioné el marco de Python en mi pregunta), pero si Python es la mejor manera de hacerlo, podría aprenderlo.
0x1ad2
Python hace que scrapy sea muy fácil. También es fácil de aprender. El mejor raspador que funciona bien en este momento es el scrapy. También tienen muy buena documentación.
Abhishek