Home > front end >  How to scrape the speech of president to dataframe?
How to scrape the speech of president to dataframe?

Time:11-16

I want to web scrape the following website: https://www.assemblee-nationale.fr/12/cri/2003-2004/20040001.asp#TopOfPage .

Here is an example of the HTML:

<html>
 <body>
  <div align="center">
   <p align="JUSTIFY">
    <strong></strong>
    <strong> M. le président </strong>
    Conformément...
    <br>
    Mes chers...
    <strong> M. Maxime </strong>
    Nous aussi!
    <br>
    <strong></strong>
   </p>
   <p align="JUSTIFY">
    <strong></strong>
    <strong> M. le président </strong>
    En ouvrant...
    <br>
    Je vous...
    <i>
     (Mmes et MM...)
     <br>
     <strong></strong>
    </i>
   </p>
  </div>
 </body>
</html>

I want to transform the website into a dataframe, where each speaker is in a column (strong) and the speech is in another column.

Here is my code:

import requests
from bs4 import BeautifulSoup
import pandas as pd

debate=[]
df=pd.DataFrame()
url = "https://www.assemblee-nationale.fr/12/cri/2003-2004/20040001.asp"
r=requests.get(url)
soup_data=BeautifulSoup(r.content, 'html.parser')
list_soup_div=soup_data.find_all('div', {'align':'center'})
for item_soup_div in list_soup_div:
    for item_soup_p in item_soup_div.find_all('p', {'align':'JUSTIFY'}):
        for br_tag in item_soup_p.find_all('br'):
            text_speech=br_tag.previous.strip()
            text_speaker=br_tag.find_previous('strong').get_text(strip=True)
            debate.append({'speaker': text_speaker, 'speech': text_speech})
df=pd.DataFrame(debate)

What I am obtaining:

speaker         speech
M. le président Conformément
M. le président Mes chers...
M. Maxime       Nous aussi!
M. le président En ouvrant...
M. le président (Mmmes et MM...)

What I want:

speaker         speech
M. le président Conformément
M. le président Mes chers...
M. Maxime       Nous aussi!
M. le président En ouvrant...
M. le président Je vous... (Mmmes et MM...)

When I have an <i>, I do not have before the <br>. That's why I am obtaining one missing speach in the example.

How I should improve my code?

CodePudding user response:

EDIT

Thanks to your comments, so lets try the other way around and decompose() all empty <strong>

for tag in soup.select('strong'):
    if len(tag.get_text(strip=True)) == 0:
        tag.decompose()

Than iterate each <strong> next_siblings and break if one of them is a <strong>:

for e in soup.select('p[align="JUSTIFY"]:not(:has(a)) >strong'):
    d = {
        'speaker':e.get_text(strip=True),
        'speech':''
        }
    for s in e.next_siblings:
        if s.name == 'strong':
            break
        else:
            d['speech'] = d['speech'] ' ' s.get_text(strip=True)
    data.append(d)

Example

import requests
from bs4 import BeautifulSoup
import pandas as pd

url = 'https://www.assemblee-nationale.fr/12/cri/2003-2004/20040001.asp'
soup = BeautifulSoup(requests.get(url).text)
data = []

for tag in soup.select('strong'):
    if len(tag.get_text(strip=True)) == 0:
        tag.decompose()

for e in soup.select('p[align="JUSTIFY"]:not(:has(a)) >strong'):
    d = {
        'speaker':e.get_text(strip=True),
        'speech':''
        }
    for s in e.next_siblings:
        if s.name == 'strong':
            break
        else:
            d['speech'] = d['speech'] ' ' s.get_text(strip=True)
    data.append(d)

pd.DataFrame(data)

Output

speaker speech
0 M. le président. La séance est ouverte.(La séance est ouverte à dix heures.)
1 M. le président. Conformément au premier alinéa de l'article 28 de la Constitution, je déclare ouverte la session ordinaire de 2003-2004.Mes chers collègues, permettez-moi d'abord de vous dire combien je suis heureux de vous retrouver tous.
2 M. Maxime Gremetz. Nous aussi !
3 M. le président. En ouvrant cette session, je tiens à me faire l'interprète de l'émotion que nous avons tous partagée face au drame qui, cet été, a endeuillé de nombreuses familles.Je vous demanderai, par conséquent, de vous lever et d'observer une minute de silence.(Mmes et MM. les députés se lèvent et observent une minute de silence.)
4 M. le président. Aux termes de l'article 10 du règlement, à l'ouverture de la session ordinaire, le président est assisté des six plus jeunes membres de l'Assemblée, qui remplissent les fonctions de secrétaires.Ce sont : M. Edouard Courtial, Mme Nathalie Kosciusko-Morizet, MM. Vincent Rolland, Sébastien Huyghe, Martial Saddier, Laurent Hénart.
5 M. le président. L'ordre du jour appelle la nomination des six vice-présidents, des trois questeurs et des douze secrétaires de l'Assemblée nationale.Pour ces diverses fonctions, les présidents des groupes ont établi une liste de candidats qui a été affichée.Je n'ai reçu aucune autre candidature.En conséquence, je proclame, dans l'ordre de leur présentation :Vice-présidents : MM. François Baroin, Jean Le Garrec, Marc-Philippe Daubresse, Rudy Salles, Mme Hélène Mignon, M. Eric Raoult ;Questeurs : MM. Henri Cuq, Claude Gaillard, Didier Migaud ;Secrétaires : MM. Jacques Brunhes, François-Michel Gonnot, Jean-Pierre Kucheida, Alain Moyne-Bressand, Germinal Peiro, Mme Marie-Françoise Pérol-Dumont, MM. Bernard Perrut, Jean Proriol, Didier Quentin, François Rochebloine, Frédéric de Saint-Sernin, Jean Ueberschlag.
6 M. le président. Je constate que le Bureau de l'Assemblée nationale est constitué.Sa composition sera notifiée à M. le Président de la République, à M. le Premier ministre, à M. le président du Sénat et publiée auJournal officiel.Le Bureau se réunira le mercredi 8 octobre, à dix-sept heures trente.
7 M. le président. Je rappelle que les six commissions permanentes sont convoquées cet après-midi à seize heures trente, pour l'élection de leur bureau, et que je réunirai la conférence des présidents à dix-huit heures.
8 M. le président. Par lettres du 2, du 12 et du 15 septembre 2003, M. le Premier ministre m'a informé que les missions temporaires précédemment confiées à MM. Jean-François Chossy, député de la Loire, Gilbert Meyer, député du Haut-Rhin, Michel Diefenbacher, député de Lot-et-Garonne, et Mme Christine Boutin, députée des Yvelines, avaient pris fin respectivement le 9, le 14 et, pour ces deux derniers, le 15 septembre 2003.
9 M. le président. J'ai reçu de M. le Premier ministre une lettre m'informant de sa décision de charger Mme Brigitte Le Brethon, députée du Calvados, d'une mission temporaire, dans le cadre des dispositions de l'article LO 144 du code électoral, auprès de M. le secrétaire d'Etat aux transports et à la mer.Cette décision a fait l'objet d'un décret publié auJournal officieldu 30 juillet 2003.J'ai reçu de M. le Premier ministre une lettre m'informant de sa décision de charger M. Christian Ménard, député du Finistère, d'une mission temporaire, dans le cadre des dispositions de l'article LO 144 du code électoral, auprès de M. le ministre de l'agriculture, de l'alimentation, de la pêche et des affaires rurales.Cette décision a fait l'objet d'un décret publié auJournal officieldu 31 juillet 2003.J'ai reçu de M. le Premier ministre une lettre m'informant de sa décision de charger M. Francis Hillmeyer, député du Haut-Rhin, d'une mission temporaire, dans le cadre des dispositions de l'article LO 144 du code électoral, auprès de M. le ministre de l'équipement, des transports, du logement, du tourisme et de la mer.Cette décision a fait l'objet d'un décret publié auJournal officieldu 28 août 2003.J'ai reçu de M. le Premier ministre une lettre m'informant de sa décision de charger M. Pierre Lang, député de la Moselle, d'une mission temporaire, dans le cadre des dispositions de l'article LO 144 du code électoral, auprès de Mme la ministre de l'écologie et du développement durable.Cette décision a fait l'objet d'un décret publié auJournal officieldu 19 septembre 2003.J'ai reçu de M. le Premier ministre une lettre m'informant de sa décision de charger M. Pierre Morel-A-L'Huissier, député de la Lozère, d'une mission temporaire, dans le cadre des dispositions de l'article LO 144 du code électoral, auprès de M. le secrétaire d'Etat aux anciens combattants.Cette décision a fait l'objet d'un décret publié auJournal officieldu 24 septembre 2003.

...


Think it is close to a still answerd closed question of you - Select your elements more specific and check if <i> is available:

for e in soup.select('p[align="JUSTIFY"]:not(:has(a)) > br'):
    data.append({
        'speaker':e.find_previous('strong').get_text(strip=True),
        'speech':' '.join((e.previous.strip(), e.next.strip(), e.find_next_sibling('i').get_text(strip=True) if e.find_next_siblings('i') else ''))
    })
  • Related