Saltar al contenido

Tácticas avanzadas de raspado de la web

Aunque los sitios web son cada vez más interactivos y fáciles de usar, esto tiene el efecto inverso en los rastreadores de la web.

Hoy en día, los sitios web modernos usan muchas prácticas de codificación dinámica que no son nada fáciles de rastrear. Algunos de los ejemplos son la carga de imágenes perezosas, el desplazamiento infinito, o elementos cargados a través de llamadas AJAX, lo que dificulta el rastreo incluso para Googlebot.

Tácticas avanzadas de raspado de la web
Tácticas avanzadas de raspado de la web

Los sitios web modernos dependen en gran medida de JavaScript para cargar elementos dinámicos.

¿Cómo saber si es una página dinámica o estática?

Puedes detectar si una página web utiliza la carga asíncrona o si es una página dinámica viendo la fuente de la página (si haces clic con el botón derecho del ratón en la página, encontrarás la opción View Page Source ). Si al buscar el contenido que buscas no lo encuentras, es probable que Javascript renderice el contenido.

Los sitios web modernos son páginas renderizadas en Javascript, lo que las hace difíciles para los web scrapers.

¿Cómo maneja el Webdriver las páginas dinámicas?

El Selenium WebDriver es una de las herramientas más populares para la automatización de la interfaz de usuario de la web. Permite la ejecución automática de las acciones realizadas en una ventana de un navegador web, como navegar a un sitio web, rellenar formularios (incluyendo el manejo de cuadros de texto, botones de radio y desplegables), enviar los formularios, navegar por páginas web, manejar ventanas emergentes, etc.

Tomemos un ejemplo de raspado de un sitio dinámico como . En este ejemplo, estaremos raspando los cursos disponibles para la palabra clave dada.

1pip instalar selenio

Shell

El enfoque para obtener la lista de cursos es escribir la palabra clave en el cuadro de entrada y luego presionar la tecla Intro (pero de manera automatizada) que navegará a la página de la lista de cursos. Entonces podemos usar BeautifulSoup para analizar el contenido. Los pasos se mencionan en el propio código.

Entonces, el guión sería:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354# .pyfrom bs4 import BeautifulSoupfrom selenium import webdriverfrom selenium.webdriver.chrome.options import Optionsfrom selenium.webdriver.common.keys import Keysfrom selenium.webdriver. support.ui import WebDriverWaitfrom selenium.common.exceptions import TimeoutExceptiondefconfigure_driver():# Agregar opciones adicionales al webdriver chrome_options = Options()# agregar el argumento y hacer que el navegador no tenga cabeza. chrome_options.add_argument("--headless")# Instanciar el Webdriver: Mencione la ruta de ejecución del webdriver que ha descargado# Para linux/Mac# driver = webdriver.Chrome(options = chrome_options)# Para windows driver = webdriver.Chrome(executable_path="./chromedriver. exe", options = chrome_options)return driverdefgetCourses(driver, search_keyword):# Paso 1: Ir a .com, sección de categorías con la palabra clave de búsqueda seleccionada driver.get(f "https://www..com/search?q={search_keyword}&categories=course")# esperar a que el elemento se cargue: WebDriverWait(driver,5).until(lambda s: s.find_element_by_id("search-results-category-target").is_displayed())except TimeoutException:print("TimeoutException: Element not found")returnNone# Paso 2: Crear un árbol de análisis de las fuentes de las páginas después de buscar soup = BeautifulSoup(driver. page_source, "lxml")# Paso 3: Iterar sobre el resultado de la búsqueda y buscar la coursefor course_page en soup.select("div.search-results-page"):for course in course_page.select("div.search-result"): title_selector ="div.search-result__info div.search-result__title a" author_selector ="div. search-result__details div.search-result__author" level_selector ="div.search-result__details div.search-result__level" length_selector ="div.search-result__details div.search-result__length "print({"title": course.select_one(title_selector).text, "author": course. select_one(selector_de_autor).text, "level": course.select_one(selector_de_nivel).text, "length": course.select_one(selector_de_longitud).text,})# crear el objeto driver.driver = configure_driver()search_keyword ="Web Scraping "getCourses(driver, search_keyword)# cerrar el driver.driver.close()

pitón

Ejecute el código de pitón anterior:

1python .py

Shell

Deberías obtener la salida de la siguiente manera:

12345...{$0027title$0027:$0027Web Scraping: Libro de datos de Python$0027, $0027autor$0027:$0027por Ian Ozsvald$0027, $0027nivel$0027:$0027principiante$0027, $0027duración$0027:$00271h 17m$0027}{$0027título$0027:$0027Raspado de páginas web dinámicas con Python y Selenio$0027, $0027autor$0027: $0027por Pratheerth Padman$0027, $0027nivel$0027:$0027Avanzado$0027, $0027duración$0027:$00271h 7m$0027}{$0027título$0027:$0027Extracción de datos estructurados de la web usando Scrapy$0027, $0027autor$0027:$0027por Janani Ravi$0027, $0027nivel$0027:$0027Principiante$0027, $0027duración$0027:$00271h 52m$0027}. ...

Shell

Manejando la carga AJAX y la carga infinita

A veces, la obtención de contenido de los sitios dinámicos es realmente sencilla, ya que dependen en gran medida de las llamadas a la API. En la carga asíncrona, la mayoría de las veces, los datos se cargan realizando solicitudes GET y POST; puedes ver estas llamadas a la API en la pestaña Red de Herramientas para Desarrolladores.

En la pestaña de red anterior, obtendrá toda la información relativa a la URL de la solicitud, los parámetros requeridos y la información del encabezado.

Veamos un ejemplo de cómo se extrae la información de los jugadores de la Premier League.Asegúrate de que proporcionas los encabezados y demás información necesaria de forma precisa. Si no proporcionas correctamente los encabezados y la información adicional, es posible que obtengas un código de estado HTTP de 401 , 403 , etc. en lugar de una respuesta 200 del servidor

1234567891011121314151617181920212223242526272829303132333435363738394041solicitudes de importaciónimport json# API urlurl ="https://footballapi.pulselive.com/football/players "# Encabezados requeridos para hacer una solicitud GET# Es una buena práctica proporcionar encabezados con cada solicitud. headers ={"content-Type": "application/x-www-form-urlencoded; charset=UTF-8", "DNT": "1", "Origin": "https://www.premierleague.com", "Referer": "https://www.premierleague.com/players", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, como Gecko) Chrome/75.0.3770.100 Safari/537. 36"}# Parámetros de la consulta necesarios para hacer get requestqueryParams ={"pageSize":32, "compSeasons":274, "altIds":True, "page":0, "type": "player", "id":-1, "compSeasonId":274}# Envío de la solicitud con url, encabezados y paramsresponse de la consulta = solicitudes. get(url = url, headers = headers, params = queryParams)# si el código de estado de la respuesta es 200 OK, entonces si la respuesta. status_code ==200:# cargar los datos json data = json.loads(response.text)# imprimir los datos requeridos para el reproductor en data["content"]:print({"nombre": player["nombre"]["display"], "nationalTeam": player["nationalTeam"]["country"], "position": player["info"]["positionInfo"]})

pitón

Es mejor inspeccionar la pestaña de la Red antes de dirigirse a la elección del Selenium WebDriver, porque llamar a un API es muy rápido comparado con manejarlo con un webdriver.

Si no funciona para ti, entonces tienes que usar el webdriver de Selenio.