Guida allo scraping di siti web dinamici con Python

Commenti: 0

Un'abilità importante per ottenere dati dalle pagine web è il web scraping. Pinterest e Instagram, che caricano dinamicamente i contenuti grazie all'interazione con gli utenti, sono esempi di questi tipi di siti web. I normali metodi di scraping sono insufficienti quando si tratta di materiale basato su JavaScript. In questo articolo, ci occuperemo di Playwright come strumento di automazione, mentre lxml verrà utilizzato per l'estrazione dei dati da questi siti dinamici che richiedono Javascript per funzionare correttamente. A questo proposito, si parlerà dell'utilizzo di proxy in Playwright per eludere il rilevamento di bot. In questa esercitazione, faremo lo scraping del profilo di Instagram per recuperare tutti gli URL dei post simulando il comportamento degli utenti, come lo scorrimento e l'attesa del caricamento dei post.

Strumenti che utilizzeremo in questa guida:

  • Playwright (per l'automazione del browser);
  • lxml (per l'estrazione dei dati tramite XPath);
  • Python (come linguaggio di programmazione).

Guida passo per passo allo scraping dei post di Instagram

Illustreremo il processo utilizzando l'esempio dello scraping di un profilo Instagram per estrarre gli URL dei post, simulando azioni dell'utente come lo scorrimento della pagina e l'attesa del caricamento di nuovi dati. I siti web dinamici caricano i loro contenuti in modo asincrono tramite richieste AJAX, il che significa che non tutti i contenuti della pagina sono immediatamente accessibili.

Passo 1. Installare le librerie necessarie

Prima di iniziare, installare i pacchetti necessari:


pip install playwright
pip install lxml

È inoltre necessario installare il browser Playwright:


playwright install

Passo 2. Impostazione di Playwright per lo scraping dinamico di siti web

Useremo Playwright per automatizzare il browser, caricare il contenuto dinamico di Instagram e scorrere la pagina per caricare altri post. Creiamo uno script di automazione di base:

Script di automazione (browser senza testa):


import asyncio
from playwright.async_api import async_playwright

async def scrape_instagram():
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True)  # Modalità senza testa Nessun feedback visivo
        page = await browser.new_page()
        
        # Visita l'URL del profilo
        await page.goto("https://www.instagram.com/profile name/", wait_until="networkidle")

        # Fare clic sul pulsante per caricare altri messaggi
        await page.get_by_role("button", name="Show more posts from").click()
        
        # Scorrere la pagina per caricare il contenuto dinamico
        scroll_count = 5  # Personalizzazione in base al numero di volte che si vuole scorrere
        for _ in range(scroll_count):
            await page.evaluate('window.scrollBy(0, 700);')
            await page.wait_for_timeout(3000)  # Attendere il caricamento dei messaggi
            await page.wait_for_load_state("networkidle")
        
        # Ottenere il contenuto della pagina
        content = await page.content()
        await browser.close()
        
        return content

# Eseguire la funzione asincrona
asyncio.run(scrape_instagram())

Passo 3. Parsing della pagina con lxml e XPath

Una volta caricato il contenuto, possiamo usare lxml per analizzare l'HTML ed estrarre i dati usando XPath. In questo caso, stiamo estraendo gli URL di tutti i post del profilo.

Parsing del contenuto della pagina ed estrazione degli URL dei post:


from lxml import html
import json

def extract_post_urls(page_content):
    # Analizzare il contenuto HTML utilizzando lxml
    tree = html.fromstring(page_content)
    
    # XPath per estrarre gli URL dei post
    post_urls_xpath = '//a[contains(@href, "/p/")]/@href'
    
    # Estrarre gli URL
    post_urls = tree.xpath(post_urls_xpath)
    
    # Convertire gli URL relativi in assoluti
    base_url = "https://www.instagram.com"
    post_urls = [f"{base_url}{url}" for url in post_urls]
    
    return post_urls

Funzione di esempio per salvare i dati estratti in formato JSON:


def save_data(profile_url, post_urls):
    data = {profile_url: post_urls}
    with open('instagram_posts.json', 'w') as json_file:
        json.dump(data, json_file, indent=4)

# Raschiare ed estrarre gli URL
page_content = asyncio.run(scrape_instagram())
post_urls = extract_post_urls(page_content)

# Salvare gli URL estratti in un file JSON
save_data("https://www.instagram.com/profile name/", post_urls)

Passo 4. Gestione dello scroll infinito con Playwright

Per effettuare lo scraping di siti web dinamici, spesso è necessario simulare lo scorrimento infinito. Nel nostro script, scorriamo la pagina utilizzando JavaScript:


(window.scrollBy(0, 700))

E attendere il caricamento dei nuovi contenuti utilizzando questo comando:


 wait_for_load_state("networkidle")

Passo 5. Uso dei proxy con Playwright

Instagram ha limiti di velocità e misure anti-bot molto rigidi. Per evitare di essere bloccati, è possibile utilizzare dei proxy per ruotare gli indirizzi IP e distribuire le richieste. Playwright consente di integrare facilmente i proxy nell'automazione dello scraping.

Implementazione dei proxy in Playwright:


async def scrape_with_proxy():
    async with async_playwright() as p:
        browser = await p.chromium.launch(
            headless=False, 
            proxy={"server": "http://your-proxy-server:port"}
        )
        page = await browser.new_page()
        await page.goto("https://www.instagram.com/profile name/", wait_until="networkidle")
        # Continuare a raschiare come prima...

Playwright supporta anche il proxy da passare come nome utente e password e l'esempio del server è riportato di seguito.


async def scrape_with_proxy():
    async with async_playwright() as p:
        browser = await p.chromium.launch(
            headless=False, 
            proxy={"server": "http://your-proxy-server:port", "username": "username", "password": "password"}
        )
        page = await browser.new_page()
        await page.goto("https://www.instagram.com/profile name/", wait_until="networkidle")
        # Continuare a raschiare come prima...

I proxy aiutano a evitare i divieti IP, le sfide CAPTCHA e assicurano lo scraping senza problemi di siti web ad alta densità di dati o con restrizioni, come Instagram.

Codice completo


import asyncio
from playwright.async_api import async_playwright
from lxml import html
import json

# Funzione di automatizzazione del browser e scraping di contenuti dinamici con proxy
async def scrape_instagram(profile_url, proxy=None):
    async with async_playwright() as p:
        # Impostare il browser con il proxy, se fornito
        browser_options = {
            'headless': True,  # Use headed browser to see the action (can set to True for headless mode)
        }
        if proxy:
            browser_options['proxy'] = proxy

        # Avviare il browser
        browser = await p.chromium.launch(**browser_options)
        page = await browser.new_page()

        # Visita la pagina del profilo Instagram
        await page.goto(profile_url, wait_until="networkidle")
        
        # Provare a fare clic sul pulsante "Mostra altri messaggi" (facoltativo, potrebbe fallire se il pulsante non viene trovato).
        try:
           await page.click('button:has-text("Show more posts from")')
        except Exception as e:
           print(f"No 'Show more posts' button found: {e}")


        # Scorrere la pagina per caricare altri messaggi
        scroll_count = 5  # Numero di scorrimenti per caricare i messaggi
        for _ in range(scroll_count):
            await page.evaluate('window.scrollBy(0, 500);')
            await page.wait_for_timeout(3000)  # Attendere il caricamento dei nuovi messaggi
            await page.wait_for_load_state("networkidle")

        # Ottenere il contenuto completo della pagina dopo lo scorrimento
        content = await page.content()
        await browser.close()  # Chiudere il browser una volta terminato
        
        return content

# Funzione per analizzare il contenuto della pagina scraped ed estrarre l'URL del post.
def extract_post_urls(page_content):
    # Analizzare il contenuto HTML utilizzando lxml
    tree = html.fromstring(page_content)
    
    # XPath per estrarre gli URL dei post
    post_urls_xpath = '//a[contains(@href, "/p/")]/@href'
    
    # Estrarre gli URL dei post usando l'XPath
    post_urls = tree.xpath(post_urls_xpath)
    
    # Convertire gli URL relativi in URL assoluti
    base_url = "https://www.instagram.com"
    post_urls = [f"{base_url}{url}" for url in post_urls]
    
    return post_urls

# Funzione per salvare gli URL dei post estratti in un file JSON
def save_data(profile_url, post_urls):
    # Strutturare i dati in formato JSON
    data = {profile_url: post_urls}
    
    # Salvare i dati in un file
    with open('instagram_posts.json', 'w') as json_file:
        json.dump(data, json_file, indent=4)
    print(f"Data saved to instagram_posts.json")

# Funzione principale per eseguire lo scraper e salvare i dati
async def main():
    # Definire l'URL del profilo Instagram
    profile_url = "https://www.instagram.com/profile name/"
    
    # Opzionalmente, impostare un proxy
    proxy = {"server": "server", "username": "username", "password": "password"}  # Utilizzare Nessuno se non è richiesto alcun proxy
    
    # Scrape della pagina Instagram con i proxy
    page_content = await scrape_instagram(profile_url, proxy=proxy)
    
    # Estrarre gli URL dei post dal contenuto della pagina raschiata
    post_urls = extract_post_urls(page_content)
    
    # Salvare gli URL dei post estratti in un file JSON
    save_data(profile_url, post_urls)

if __name__ == '__main__':
   asyncio.run(main())

Strumenti di automazione alternativi per il web scraping

Mentre Playwright è una scelta eccellente per lo scraping di siti web dinamici, altri strumenti potrebbero essere adatti a scenari diversi:

  1. Selenium: Selenium è uno dei più vecchi framework di automazione del browser e funziona in modo simile a Playwright. È molto versatile, ma manca di alcune capacità moderne che Playwright offre, come la gestione di più browser con una singola API;
  2. Puppeteer: Puppeteer è un altro strumento molto diffuso per l'automazione dei browser, soprattutto per lo scraping di siti web ad alto contenuto di JavaScript. Come Playwright, controlla i browser headless e permette l'interazione con i contenuti dinamici;
  3. Requests + BeautifulSoup: per i siti web più semplici che non richiedono JavaScript per caricare il contenuto, la libreria Requests combinata con BeautifulSoup è un'alternativa leggera. Tuttavia, non gestisce bene i contenuti dinamici.

Ogni strumento offre punti di forza unici e può essere scelto in base alle esigenze e alle condizioni specifiche del progetto.

Per uno scraping di successo di siti web dinamici che utilizzano attivamente JavaScript e richieste AJAX, sono necessari strumenti potenti in grado di gestire in modo efficiente lo scorrimento infinito e gli elementi interattivi complessi. Una di queste soluzioni è Playwright, uno strumento di Microsoft che offre un'automazione completa del browser, il che lo rende una scelta ideale per piattaforme come Instagram. In combinazione con la libreria lxml per l'analisi dell'HTML, Playwright semplifica notevolmente l'estrazione dei dati, consentendo di automatizzare le interazioni con gli elementi della pagina e il processo di analisi senza interventi manuali. Inoltre, l'uso di server proxy aiuta a eludere la protezione anti-bot e previene il blocco dell'IP, garantendo operazioni di scraping stabili e ininterrotte.

Commenti:

0 Commenti