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)
4 Réponses :
Essayez plutôt d'utiliser find_all, notez que cela renverra une liste de nœuds au lieu d'un seul nœud.
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.
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 :).
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)
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)