3
votes

Comment gratter plusieurs tableaux d'une page dans une page wikipedia?

J'essaye de rassembler tous les tableaux de la page suivante en un seul grand tableau; https://en.wikipedia.org/wiki/List_of_QI_episodes

Mais le problème est mon code ne semble télécharger que la table pilote et aucun des autres. J'ai regardé le html et j'ai remarqué qu'ils avaient tous la même classe, alors comment faire la différence entre eux.

Merci d'avance.

import requests
import pandas as pd
from bs4 import BeautifulSoup
page = requests.get("https://en.wikipedia.org/wiki/List_of_QI_episodes")
soup = BeautifulSoup(page.content, "lxml")
My_table = soup.find("table",{"class":"wikitable plainrowheaders wikiepisodetable"})
print(My_table)


0 commentaires

4 Réponses :


2
votes

Essayez plutôt d'utiliser find_all, notez que cela renverra une liste de nœuds au lieu d'un seul nœud.


0 commentaires

2
votes

Si vous souhaitez cibler toutes les tables, vous pouvez simplement sélectionner toutes les tables qui correspondent à vos critères. select renverra toutes les tables:

import requests
from bs4 import BeautifulSoup
page = requests.get("https://en.wikipedia.org/wiki/List_of_QI_episodes")
soup = BeautifulSoup(page.content, "lxml")
for tid in ('Pilot', 'Series_A_\\.282003\\.29'):
    table = soup.select_one("h3:has(span#{}) + table.wikitable.plainrowheaders.wikiepisodetable".format(tid))
    print(table)

Si vous souhaitez cibler chaque table individuellement, vous pouvez utiliser le sélecteur : has () pour cibler l'en-tête avant la table qui contient l ' id spécifique que vous souhaitez , suivi du combinateur + qui trouvera le prochain enfant. Voici un exemple simple ciblant deux des tables.

import requests
from bs4 import BeautifulSoup
page = requests.get("https://en.wikipedia.org/wiki/List_of_QI_episodes")
soup = BeautifulSoup(page.content, "lxml")
print(soup.select("table.wikitable.plainrowheaders.wikiepisodetable")

Vous pouvez étendre une logique similaire pour cibler ce que vous voulez.

EDIT: Utilisez select_one dans le deuxième exemple car nous ciblons une seule table par opposition à plusieurs tables.


3 commentaires

J'aime ça. Pourquoi, par exemple, h3: has (span # Pilot) ne sélectionne-t-il rien si je l'utilise via devtools sur la page elle-même? Version Chrome 71.0.3578.98 (version officielle) (64 bits)


Vous devez activer le drapeau expérimental Fonctionnalités de la plate-forme Web expérimentale , dans chrome: // flags (mais cela peut causer des problèmes sur certaines pages, je ne recommanderais donc pas de le laisser activé ). : has () est un sélecteur de niveau 4 prévu pour le profil instantané seulement. Peu de gens l'ont implémenté, et c'est un peu expérimental, mais pour le scraping, cela peut être très utile, c'est pourquoi je l'ai implémenté dans Soup Sieve (la bibliothèque de sélection sous-jacente).


Il est également possible que les sélecteurs soient confus et que Chrome ne le prenne pas en charge même avec le drapeau activé: developer.mozilla.org/en-US/docs/Web/CSS/... . J'en ai testé tellement pendant le développement que je me trompe peut-être sur ceux qui sont pris en charge dans les navigateurs :).



0
votes

Au lieu de find, utilisez find_all. find_all renvoie tous les nœuds avec les propriétés correspondantes alors que find renvoie uniquement le premier nœud.

import requests
import pandas as pd
from bs4 import BeautifulSoup
page = requests.get("https://en.wikipedia.org/wiki/List_of_QI_episodes")
soup = BeautifulSoup(page.content, "lxml")
my_tables = soup.find_all("table",{"class":"wikitable plainrowheaders wikiepisodetable"})
for table in my_tables:
    print(table)


0 commentaires

0
votes

Vous pouvez également utiliser des pandas read_html

import requests
import pandas as pd

url = 'https://en.wikipedia.org/wiki/List_of_QI_episodes'
re = requests.get(url, headers =  {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'})
df = pd.read_html(re.text)
print(df)


0 commentaires