How could I extract the content of an article from a html webpage using python Beautiful Soup?

Viewed 64

I am a novice wiht python and I am trying to do webscraping as exercise. I would like to scrape the content, and the title of each article inside a web page . I have a problem with my code because I do not think is very efficient and I would like to optimize it.

the page I am trying to scrape is https://www.ansa.it/sito/notizie/politica/politica.shtml

this is what I have done so far:

#libraries
from bs4 import BeautifulSoup
from bs4 import BeautifulSoup as soup
import requests
import pandas as pd
import urllib.request,sys,time
import csv
from csv import writer
import time
from datetime import datetime

r= requests.get('https://www.ansa.it/sito/notizie/politica/politica.shtml')
b= soup(r.content, 'lxml')

title=[]
links=[]
content=[]

for c in b.findAll('h3',{'class':'news-title'}):
   title.append(c.text.strip())  
for c in b.findAll("h3", {"class": "news-title"}):
    links.append(c.a["href"])
for link in links: 
    page=requests.get('https://www.ansa.it'+link)
    bsjop=soup(page.content)
    for n in bsjop.findAll('div',{'itemprop': 'articleBody'}):
        content.append(n.text.strip())

The problem is that my output is made of multiple links, multiple titles and multiple contents that do not match each other (like one article has title and a content that has nothing to do with it)

If you know ways that I can improve my code it would be nice thanks

3 Answers

To get all articles titles, urls, texts into a Pandas DataFrame you can use next example (I used tqdm module to get nice progress bar):

import requests
from tqdm import tqdm
from bs4 import BeautifulSoup


url = "https://www.ansa.it/sito/notizie/politica/politica.shtml"
soup = BeautifulSoup(requests.get(url).content, "html.parser")

all_data = []
for title in tqdm(soup.select("h3.news-title")):
    t = title.get_text(strip=True)
    u = title.a["href"]
    s = BeautifulSoup(
        requests.get("https://www.ansa.it" + u).content, "html.parser"
    )
    text = s.select_one('[itemprop="articleBody"]')
    text = text.get_text(strip=True, separator="\n") if text else ""

    all_data.append([t, u, text])


df = pd.DataFrame(all_data, columns=["Title", "URL", "Text"])
df.to_csv("data.csv", index=False)

Creates data.csv (screenshot from LibreOffice):

enter image description here

import requests
from bs4 import BeautifulSoup
import pandas as pd

news_list = []
r = requests.get('https://www.ansa.it/sito/notizie/politica/politica.shtml')
soup = BeautifulSoup(r.text, 'html.parser')
articles = soup.select('article.news')
for art in articles:
    try:
        title = art.select_one('h3').text.strip()
        if 'javascript:void(0);' in art.select('a')[0].get('href'):
            url = 'https://www.ansa.it' + art.select('a')[1].get('href')
        else:
            url = 'https://www.ansa.it' + art.select('a')[0].get('href')
        r = requests.get(url)
        soup = BeautifulSoup(r.text, 'html.parser')
        content = soup.select_one('div.news-txt').text.strip()
        print(f'retrieving {url}')
        news_list.append((title, content, url))
    except Exception as e:
        print(art.text.strip(), e)

df = pd.DataFrame(news_list, columns = ['Title', 'Content', 'Url'])
print(df)

This will return some errors for some links on page, which you will have to investigate and debug (and ask for help if you need it - it's an important part of learning process), and a dataframe with the list successfully retrieved, which looks like this:

    Title   Content Url
0   Letta: 'Ora difficile ricomporre con M5s'. Mel...   Partiti scossi dallo scioglimento anticipato d...   https://www.ansa.it/sito/notizie/politica/2022...
1   L'emozione di Draghi: 'Ancheil cuore dei banch...   "Certe volte anche il cuore dei banchieri cent...   https://www.ansa.it/sito/notizie/politica/2022...
2   La giornata di Draghi in foto       https://www.ansa.it/sito/photogallery/primopia...
3   Il timing del voto, liste entro un mese. A Fer...   Le liste dei candidati entro un mese a partire...   https://www.ansa.it/sito/notizie/politica/2022...
4   Si lavora sulla concorrenza, ipotesi stralcio ...   Il DDL Concorrenza andrà in Aula alla Camera l...   https://www.ansa.it/sito/notizie/economia/2022...
5   Le cifre del governo Draghi: 55 voti fiducia e...   Una media di 7,4 leggi approvate ogni mese su ...   https://www.ansa.it/sito/notizie/politica/2022...
6   I 522 giorni del governo Draghi LE FOTO L'arrivo di SuperMario, gli incontri, le allea...   https://www.ansa.it/sito/photogallery/primopia...
7   Presidi, disappunto per le urne in autunno, ci...   "C'è disappunto non preoccupazione per le urne...   https://www.ansa.it/sito/notizie/politica/2022...
8   Ucraina: Di Maio,sostegno ricerca mercati alte...   (ANSA) - ROMA, 22 LUG - Lo scoppio del conflit...   https://www.ansa.it/sito/photogallery/primopia...
9   Il giorno più lungo: dal Senato fiducia a Drag...   Passa la fiducia al premier Draghi in Senato, ...   https://www.ansa.it/sito/notizie/politica/2022...
10  Oltre mille sindaci a sostegno di Draghi    Nei giorni che attendono il mercoledì che deci...   https://www.ansa.it/sito/notizie/politica/2022...
11  Mattarella scioglie le Camere, si vota il 25 s...   E' stata una scelta "inevitabile", il voto del...   https://www.ansa.it/sito/notizie/politica/2022...
12  Camere sciolte ma il vitalizio è salvo  Nonostante lo scioglimento delle Camere antici...   https://www.ansa.it/sito/notizie/politica/2022...
13  Ultimatum di Conte, risposte o fuori. Di Maio:...   Senza "risposte chiare" il Movimento 5 Stelle ...   https://www.ansa.it/sito/notizie/politica/2022...
14  Di Maio, Conte sta compiendo una vendetta poli...   Se le cose restano come sono oggi "Mario Dragh...   https://www.ansa.it/sito/notizie/politica/2022...
15  Governo: mercoledì la fiducia fiducia prima al...   Le comunicazioni del presidente del Consiglio ...   https://www.ansa.it/sito/notizie/politica/2022...
16  Il giorno più lungo: dal Senato fiducia a Drag...   Passa la fiducia al premier Draghi in Senato, ...   https://www.ansa.it/sito/notizie/politica/2022...
17  Mattarella scioglie le Camere, si vota il 25 s...   E' stata una scelta "inevitabile", il voto del...   https://www.ansa.it/sito/notizie/politica/2022...
18  Il discorso di Draghi al Senato 'Partiti, pron...   "Siamo qui perché lo hanno chiesto gli italian...   https://www.ansa.it/sito/notizie/politica/2022...
19  Governo: mercoledì la fiducia fiducia prima al...   Le comunicazioni del presidente del Consiglio ...   https://www.ansa.it/sito/notizie/politica/2022...
20  Draghi al Senato per una fiducia al buio. Prem...   Draghi al bivio tra governo e crisi. Alle 9.30...   https://www.ansa.it/sito/notizie/politica/2022...
21  Ultimatum di Conte, risposte o fuori. Di Maio:...   Senza "risposte chiare" il Movimento 5 Stelle ...   https://www.ansa.it/sito/notizie/politica/2022...
22  Camere sciolte ma il vitalizio è salvo  Nonostante lo scioglimento delle Camere antici...   https://www.ansa.it/sito/notizie/politica/2022...

You don't need two different loops if you are referring to the same element. Try the below code to save the title and links.

for c in b.findAll('h3',{'class':'news-title'}):
   title.append(c.text.strip()) 
   links.append(c.a["href"])

By combining you will be sure that the title and link are scraped from the same element.

Related