Creazione di uno scraper di feed RSS con Python

Questo articolo è la prima parte 1 di un tutorial relativo alla creazione di un’applicazione di web scraping con Python. In questo articolo ci concentriamo ad approfondire le librerie Requests e BeautifulSoup.

Nella 2° parte del tutorial vedremo come schedulare lo scraping tramite Celery.

Nella 3° parte descriviamo come realizzazione di un’applicazione web scraping con Django.

Il codice di questo articolo è disponibile pubblicamente su GitHub.

Requisiti

Ho già utilizzato lo scraping web in diversi modi all’interno dei miei progetti, che si tratti di raccolta di dati per l’analisi, creazione di notifiche quando i siti vengono modificati o creazione di applicazioni web.

Questo articolo illustrerà un semplice  di feed RSS per HackerNews. Il feed RSS, disponibile a questo link, prevede aggiornamenti a intervalli regolari per i  nuovi post e attività sul sito.

Sebbene ciò possa essere ottenuto utilizzando un lettore RSS, questo è inteso come un  semplice esempio di utilizzo di Python, che può essere adattato facilmente ad altri siti Web.

In questo esempio usiamo:

Obiettivi

Di seguito uno schema dei passaggi da prevedere per creare la nostra applicazione:

  1. Creazione della directory  del progetto e del file scraping.py.
  2. Verificare che possiamo eseguire il ping del feed RSS che sarà oggetto dello scraping.
  3. Scraping del contenuto XML del sito.
  4. Analisi del contenuto utilizzando BS4.
  5. Output del contenuto in un file .txt

Inizializzazione

Il primo passo è la creazione della directory del progetto e accedere a quella directory tramite riga di comando. Una volta all’interno della directory di progetto, creiamo il file di progetto.

Nota: in questo caso stiamo usando Ubuntu, quindi questi comandi potrebbero differire a seconda del sistema operativo.

            $ mkdir web_scraping_example && cd web_scraping_example

$ touch scraping.py
        
Successivamente è necessario installare le librerie Python previste dai requisiti. Si può usare il comando pip, come nell’esempio seguente:
            $ pip install requests
$ pip install bs4
        

Importazione delle librerie

Ora che le basi del progetto sono state impostate, possiamo iniziare a scrivere il codice del web scraping.

All’interno del file scraping.py, si deve importare le librerie che abbiamo installato utilizzando pip.

            # scraping.py

import requests
from bs4 import BeautifulSoup
        

Quanto sopra ci consente di utilizzare le funzioni fornite dalle librerie Requests e BeautifulSoup.

Ora possiamo iniziare a testare la capacità di eseguire il ping del feed RSS di HackerNews e scrivere lo script di scraping.

Nota: di seguito non includeremo le righe di importazione. Tutto il codice che rimane uguale verrà annotato come ‘…’ sopra o sotto le nuove righe.

Testare la richiesta

Quando eseguiamo lo scraping web, iniziamo inviando una richiesta a un sito web. Per assicurarci di essere in grado di eseguire lo scraping, dobbiamo verificare che  possiamo stabilre una connessione al sito.

Iniziamo creando la nostra funzione di scraping di base. Questo sarà ciò a cui eseguiremo

            # scraping.py

# library imports
...

# scraping function
def hackernews_rss('https://news.ycombinator.com/rss'):
    try:
        r = requests.get()
        return print('The scraping job succeeded: ', r.status_code)
    except Exception as e:
        print('The scraping job failed. See exception: ')
        print(e)
        
        
print('Starting scraping')
hackernews_rss()
print('Finished scraping')
        

Nel codice di cui sopra,  si richiama la funzione requests.get(...) della libreria Requests per recuperare il sito Web da analizzare. Quindi si stampa a video lo stato della richiesta, contenuto nel parametro r.status_code, per verificare che il sito Web sia stato chiamato correttamente.
Inoltre, abbiamo inserito tutto dentro un try: except: in modo da rilevare eventuali errori che si potremmo verificare in seguito.

Una volta eseguito lo script, si ottiene un codice di stato pari a 200. Questo conferma che siamo in grado di eseguire il ping del sito e “ottenere” informazioni.

            $ python scraping.py

Starting scraping
The scraping job succeeded: 200
Finsihed scraping
        

Scraping del contenuto

Il nostro script ha restituito un codice di stato pari a 200, siamo pronti per iniziare ad estrarre il contenuto XML dal sito. A tal fine, dobbiamo utilizzare BS4 insieme a Requests.
            # scraping.py

...

def hackernews_rss():
    try:
        r = requests.get('https://news.ycombinator.com/rss')
        soup = BeautifulSoup(r.content, features='xml')
        
        return print(soup)
...
        

Questo codice assegne il contenuto XML acquisito da HackerNews alla variabile soup. Stiamo usando r.content per passare l’XML restituito a BeautifulSoup, che analizzeremo nel prossimo paragrafo.

Una cosa fondamentale da notare è che stiamo sfruttando il parametro features='xml', questo parametro varia a seconda dei dati da acquisire (ad esempio, in un scraper HTML si dichiarerà come ‘HTML’).

L’output di quanto sopra sarà un gran disordine di contenuti che non ha molto senso. Questo è solo per visualizzare quali informazioni stiamo estraendo con successo dal sito web.

Analisi dei dati

Abbiamo descritto come possiamo estrarre l’XML dal feed RSS di HackerNews. E’ quindi il momento di analizzare le informazioni.

Abbiamo scelto di usare il feed RSS perché è molto più semplice da analizzare rispetto alle informazioni html del sito Web, poiché non dobbiamo preoccuparci degli elementi HTML nidificati e di individuare le informazioni esatte.

Iniziamo osservando la struttura del feed:

            <item>
    <title>...</title>
    <link>...</link>
    <pubDate>...</pubDate>
    <comments>...</comments>
    <description>...</description>
</item>
        

Ciascuno dei tag disponibili sul feed RSS segue la struttura di cui sopra, contenente tutte le informazioni all’interno dei tag <item>...</item>.

Sfruttiamo la coerenza dei tag item per analizzare le informazioni.

            # scraping.py 

...

def hackernews_rss():
    article_list = []
    try:
        r = requests.get('https://news.ycombinator.com/rss')
        soup = BeautifulSoup(r.content, features='xml')
        articles = soup.findAll('item')        
        for a in articles:
            title = a.find('title').text
            link = a.find('link').text
            published = a.find('pubDate').text
            article = {
                'title': title,
                'link': link,
                'published': published
                }
            article_list.append(article)
        return print(article_list)
...
        

In questo codice, effettuiamo un controllo di tutti gli item in articles = soup.findAll('item'). Questo consente di estrarre ciascuno dei tag <item>...</item> dall’XML che abbiamo acquisito.

Ciascuno degli articoli viene analizzato utilizzando il ciclo: for a in articles:, questo consente di analizzare le informazioni in variabili separate e aggiungerle a un dizionario vuoto che abbiamo creato prima del ciclo.
BS4 ha scomposto l’XML in una stringa, consentendoci di chiamare la funzione .find() per cercare i tag in ciascuno degli oggetti. Usando .text siamo in grado di estrarre gli elementi <tag>...</tag> e salvare solamente il testo.
I risultati sono inseriti in un elenco tramite il comando article_list.append(article) in modo da potervi accedere in seguito.

Infine inseriamo la stampa della lista degli articoli in modo da visualizzare un output durante l’esecuzione dello script di scraping.

Output in un file

Il feed RSS è stato ora inviato correttamente in una funzione print() per visualizzare l’elenco prodotto a termine del parsing. Ora possiamo inserire i dati in un file .txt, in modo che possano riessere utilizzati in future analisi e altre attività relative ai dati. Utilizziamo la libreria JSON per la visualizzazione dei dati più semplice per noi; tuttavia, descriviamo anche un esempio senza la libreria JSON.

Iniziamo creando un’altra funzione def save_function(): che elabora l’elenco prodotto dalla funzione hackernews_rss(). In questo modo sarà più facile apportare modifiche in futuro.

            # scraping.py
import json

...

def save_function(article_list):
    with open('articles.txt', 'w') as outfile:
        json.dump(article_list, outfile)

...
        

Quanto sopra utilizza la libreria JSON per scrivere l’output dello scraping nel file articles.txt. Questo file verrà sovrascritto durante l’esecuzione dello script.

Un altro metodo per scrivere nel file .txt prevede un ciclo for:

            # scraping.py

...

def save_function(article_list):
    with open('articles.txt', 'w') as f:
        for a in article_list:
            f.write(a+'\n')
        f.close()
        
...
        
Ora che abbiamo creato la funzione save_function(), possiamo adattare la funzione di scraping per salvare i dati.
            # scraping.py

...

def hackernews_rss():
    ...
    try:
        ...
        return save_function(article_list)

...
        

Modificando il comando return print(article_list) in return save_function(article_list) siamo in grado di inserire i dati in un file .txt.

L’esecuzione dello script produrrà ora un file .txt dei dati acquisiti dal feed RSS di HackerNews.

Conclusione

Abbiamo creato con successo uno script Python per il di scraping dei feed RSS utilizzando Requests e BeautifulSoup. Questo ci consente di analizzare le informazioni XML in un formato leggibile con cui lavorare in futuro.

Questo script è la base per costruire alcune funzionalità interessanti:

  • Scraping di informazioni più complesse utilizzando elementi HTML.
  • Utilizzo di Selenium per lo scraping di siti dove il rendering lato client rende inutile l’uso di Requests.
  • Creazione di un’applicazione Web che acquisirà i dati dello scraping e li visualizzerà (ad esempio, un aggregatore)
  • Estrazione di dati da siti Web a seconda di una pianificazione e schedulazione.


Sebbene questo articolo abbia  descritto le basi del web scraping, possiamo iniziare ad approfondire alcuni dettagli.

Possiamo inserire questo script all’interno di una sequenza di altri script, schedulati tramite  Celery, oppure possiamo aggregare le informazioni su un’applicazione web utilizzando Django.

Questo articolo fa parte di una serie in 3 parti in cui descriviamo semplici esempi di web scraping e aggregazione su base programmata.

Recommended Posts

No comment yet, add your voice below!


Add a Comment

Il tuo indirizzo email non sarà pubblicato.