Extraire une valeur d'attribut avec beautifulsoup

112

J'essaye d'extraire le contenu d'un seul attribut de «valeur» dans une balise «d'entrée» spécifique sur une page Web. J'utilise le code suivant:

import urllib
f = urllib.urlopen("http://58.68.130.147")
s = f.read()
f.close()

from BeautifulSoup import BeautifulStoneSoup
soup = BeautifulStoneSoup(s)

inputTag = soup.findAll(attrs={"name" : "stainfo"})

output = inputTag['value']

print str(output)

J'obtiens un TypeError: les index de liste doivent être des entiers, pas str

même si d'après la documentation de Beautifulsoup, je comprends que les chaînes ne devraient pas être un problème ici ... mais ce n'est pas un spécialiste et j'ai peut-être mal compris.

Toute suggestion est grandement appréciée! Merci d'avance.

Barnabe
la source

Réponses:

150

.find_all() renvoie la liste de tous les éléments trouvés, donc:

input_tag = soup.find_all(attrs={"name" : "stainfo"})

input_tagest une liste (contenant probablement un seul élément). En fonction de ce que vous voulez exactement, vous devez soit faire:

 output = input_tag[0]['value']

ou utilisez une .find()méthode qui ne renvoie qu'un (premier) élément trouvé:

 input_tag = soup.find(attrs={"name": "stainfo"})
 output = input_tag['value']
Łukasz
la source
Super truc! Merci. maintenant, j'ai une question sur l'analyse de la sortie qui est un long tas de caractères non-ASCII, mais je poserai cela dans une question séparée.
Barnabe
3
ne devrait pas être accédé à la «valeur» selon stackoverflow.com/questions/2616659/… . Qu'est-ce qui fait fonctionner le code ci-dessus dans ce cas? Je pensais que vous devriez accéder à la valeur en faisantoutput = inputTag[0].contents
Seth
@Seth - non, car il recherche l'attribut 'value' de la balise d'entrée, et .contents renvoie le texte encapsulé par la balise (<span> je suis .contents </span>) - (je réponds juste maintenant parce que j'avais pour vérifier ce qui se passait; imaginez que quelqu'un d'autre pourrait en bénéficier)
Dolan Antenucci
1
très bonne réponse. cependant, j'utiliserais à la inputTag[0].get('value') place de inputTag[0]['value']pour empêcher aucun pointeur au cas où la balise ne serait pas un attribut de valeur
amphibient
Qu'en est-il des liens qui ne sont pas directement liés à la page d'accueil du site Web en visite, Comment obtenir tous les liens, qu'ils soient liés directement ou indirectement à la page Web.
Patinoire16
26

Dans Python 3.x, utilisez simplement get(attr_name)sur votre objet tag que vous utilisez find_all:

xmlData = None

with open('conf//test1.xml', 'r') as xmlFile:
    xmlData = xmlFile.read()

xmlDecoded = xmlData

xmlSoup = BeautifulSoup(xmlData, 'html.parser')

repElemList = xmlSoup.find_all('repeatingelement')

for repElem in repElemList:
    print("Processing repElem...")
    repElemID = repElem.get('id')
    repElemName = repElem.get('name')

    print("Attribute id = %s" % repElemID)
    print("Attribute name = %s" % repElemName)

contre un fichier XML conf//test1.xmlqui ressemble à:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
    <singleElement>
        <subElementX>XYZ</subElementX>
    </singleElement>
    <repeatingElement id="11" name="Joe"/>
    <repeatingElement id="12" name="Mary"/>
</root>

imprime:

Processing repElem...
Attribute id = 11
Attribute name = Joe
Processing repElem...
Attribute id = 12
Attribute name = Mary
amphibie
la source
Cela vous dérangerait-il si je modifiais ceci pour suivre PEP 8 et utiliser les méthodes de formatage de chaîne plus modernes?
AMC
C'est bien, allez-y
amphibient
6

Si vous souhaitez récupérer plusieurs valeurs d'attributs à partir de la source ci-dessus, vous pouvez utiliser findAllet une liste de compréhension pour obtenir tout ce dont vous avez besoin:

import urllib
f = urllib.urlopen("http://58.68.130.147")
s = f.read()
f.close()

from BeautifulSoup import BeautifulStoneSoup
soup = BeautifulStoneSoup(s)

inputTags = soup.findAll(attrs={"name" : "stainfo"})
### You may be able to do findAll("input", attrs={"name" : "stainfo"})

output = [x["stainfo"] for x in inputTags]

print output
### This will print a list of the values.
Margath
la source
4

Je vous suggère en fait un moyen de gagner du temps en supposant que vous savez quel type de balises possède ces attributs.

supposons qu'une balise xyz ait cette attritube nommée "staininfo" ..

full_tag = soup.findAll("xyz")

Et je ne veux pas que vous compreniez que full_tag est une liste

for each_tag in full_tag:
    staininfo_attrb_value = each_tag["staininfo"]
    print staininfo_attrb_value

Ainsi, vous pouvez obtenir toutes les valeurs attrb de staininfo pour toutes les balises xyz

b1tchacked
la source
3

vous pouvez également utiliser ceci:

import requests
from bs4 import BeautifulSoup
import csv

url = "http://58.68.130.147/"
r = requests.get(url)
data = r.text

soup = BeautifulSoup(data, "html.parser")
get_details = soup.find_all("input", attrs={"name":"stainfo"})

for val in get_details:
    get_val = val["value"]
    print(get_val)
Monsieur Os
la source
En quoi cela diffère-t-il des réponses beaucoup plus anciennes qui étaient déjà là?
AMC
0

J'utilise ceci avec Beautifulsoup 4.8.1 pour obtenir la valeur de tous les attributs de classe de certains éléments:

from bs4 import BeautifulSoup

html = "<td class='val1'/><td col='1'/><td class='val2' />"

bsoup = BeautifulSoup(html, 'html.parser')

for td in bsoup.find_all('td'):
    if td.has_attr('class'):
        print(td['class'][0])

Il est important de noter que la clé d'attribut récupère une liste même lorsque l'attribut n'a qu'une seule valeur.

PeterXX
la source