Je racle une page Web et j'écris la sortie dans un fichier .csv. J'obtiens une erreur "index de liste hors limites". Je pense que je comprends ce que signifie l'erreur, mais je ne sais pas comment la corriger.
Le code HTML qui héberge les conteneurs sur lesquels je veux itérer ressemble à ceci:
booth_number = cols[3].text
la ligne 5 semble commencer par une balise non autorisée et aucune balise
Êtes-vous sûr à 100% que
container.findAll ("td")renverra toujours une liste dont la longueur est de 4 ou plus? Si tel est le cas, pouvez-vous le confirmer en ajoutantprint (len (cols))juste après cette ligne? Sinon, que doit-il se passer lorsquecolsest trop court? (Autre que s'écraser)Cet exemple de HTML a un avec six enfants, mais il doit y avoir d'autres éléments dans le HTML complet avec trop peu de s.
que vous attendez, comme d'autres l'ont suggéré
, n'est-ce pas? Et je peux résoudre ce problème en utilisant
0
0 commentaires
1
5 commentaires
s, mais c'est assez facile à nettoyer.
0
1 commentaires
Bizarrement, votre code fonctionne bien pour moi. Py3 et BS4. Cela implique que votre page_html n'a pas toujours le nombre de
Merci a tous. Je pense que cela a du sens pour moi. Il y a d'autres conteneurs dans le HTML qui n'ont pas le même nombre de
len (cols)?@Kevin J'obtiens "7" quand j'ajoute
print (len (cols))aprèscols = container.findAll ("td")Vous devez répondre à la question "Qu'est-ce que je veux faire s'il y a moins de six colonnes dans la ligne actuelle?" Voulez-vous ignorer complètement la ligne ou voulez-vous récupérer ce que vous pouvez et utiliser des valeurs d'espace réservé pour le reste?
@JohnGordon Je pense que je veux aller chercher ce que je peux et utiliser un numéro d'espace réservé pour le reste.
3 Réponses :
votes
Il n'y a pas autant de colonnes que vous le supposez.
Vous pouvez voir combien de colonnes il y a avec
len (cols), et en fonction de cela, décider quoi faire lorsque cette colonne attendue n'est pas là.Notez que vous rencontrerez un problème similaire avec la ligne qui suit.
votes
Le problème est que le tableau cols a une longueur inférieure à l'élément auquel vous essayez d'accéder. Dans l'exemple
if len(cols) > 3: booth_number = cols[3].textle tableau cols a une longueur de 3 ou moins car l'indexation du tableau est de base zéro (l'élément 1 a un index de 0). Lorsque vous essayez d'accéder au quatrième élément avec un index de 3, vous accédez à un élément en dehors de la plage.
Vous pouvez remédier à cela en vérifiant la longueur avant d'accéder à l'élément.
de cette façon, si le numéro de stand n'est pas dans les cols, votre programme n'échoue pas et ne s'arrête pas.
Cela dépend, vous pouvez l'ajouter avant chaque accès au tableau cols, donc vous auriez si len (cols)> 1: company_name = cols [1] .find ("a"). Text si len (cols)> 2: numéro_booth = cols [2] .text ... etc. Ou, si l'enregistrement est inutile sans toutes les colonnes, vous pouvez simplement vérifier la longueur complète avant de traiter la ligne, afin que vous puissiez obtenir vos colonnes avec cols = container.findAll ("td") puis faire un if len ( cols)> 5: récupérez vos données.
Donc: `` `pour conteneur dans des conteneurs: cols = container.findAll (" td ") if len (cols)> 1: company_name = cols [1] .find (" a "). Text if len (cols)> 2 : booth_number = cols [2] .text si len (cols)> 3: category = cols [3] .text.strip () if len (cols)> 5: country = cols [5] .text ''
Lorsque j'ajoute le code ci-dessus, j'obtiens maintenant une erreur "AttributeError:" NoneType "object has no attribute" text "".
Vous pouvez également ajouter du code pour vérifier Aucun. Lors du grattage, vous aurez souvent besoin de tout vérifier avant d'essayer d'accéder car vous ne pouvez jamais vraiment être sûr qu'il est là. Vous pouvez faire si len (cols)> 1: col_1 = cols [1] .find ("a") si col_1 n'est pas None: nom_entreprise = col_1.text. Ensuite, vous faites cela pour chaque élément de données et vous obtiendrez simplement des valeurs vides pour les éléments qui n'existent pas, mais vous vous retrouverez avec votre ensemble de données.
Ça a marché! Le seul problème maintenant est que mon code
del containers [8]ne saute pas les 7 premiersvotes
Certaines lignes du fichier .csv n'ont pas autant de colonnes que prévu. Il semble que vous pensez que le nombre de colonnes devrait être cohérent, il vous suffit donc de vérifier avant de commencer à indexer la ligne comme suit:
for container in containers: if len(cols) == 7: cols = container.findAll("td") company_name = cols[1].find("a").text booth_number = cols[2].text category = cols[3].text.strip() country = cols[5].text company_names.append(company_name) booth_numbers.append(booth_number) categories.append(category) countries.append(country) csv_out.writerow([company_name, booth_number, category, country])Je suppose qu'il y aura 7 colonnes car c'est ce que vous avez calculé pour la première ligne, mais vous pouvez changer cela pour ce qu'il devrait être.
Cela a fonctionné en termes d'élimination de l'erreur, mais le fichier .csv produit est vide.
Articles qui pourrait vous intéresser :
Python: ConnectionError: HTTPSConnectionPool (hôte = 'api.foursquare-com', port = 443)L'exécution de Flask sous Windows n'exécute pas la commande d'exécution de flask
Chatbot installé mais obtention d'une erreur lors de l'importation de ChatBot
Administrateur Django: __str__ a renvoyé une non-chaîne (type int)