Extrahieren eines Attributwerts mit beautifulsoup

109

Ich versuche, den Inhalt eines einzelnen "Wert" -Attributs in einem bestimmten "Eingabe" -Tag auf einer Webseite zu extrahieren. Ich benutze den folgenden Code:

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)

Ich erhalte einen TypeError: Listenindizes müssen Ganzzahlen sein, nicht str

Obwohl ich aus der Beautifulsoup-Dokumentation verstehe, dass Strings hier kein Problem sein sollten ... aber ich bin kein Spezialist und habe sie möglicherweise falsch verstanden.

Jeder Vorschlag wird sehr geschätzt! Danke im Voraus.

Barnabe
quelle

Antworten:

146

.find_all() Gibt eine Liste aller gefundenen Elemente zurück, also:

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

input_tagist eine Liste (die wahrscheinlich nur ein Element enthält). Je nachdem, was Sie genau wollen, sollten Sie entweder Folgendes tun:

 output = input_tag[0]['value']

oder verwenden Sie eine .find()Methode, die nur ein (erstes) gefundenes Element zurückgibt:

 input_tag = soup.find(attrs={"name": "stainfo"})
 output = input_tag['value']
Łukasz
quelle
Tolles Zeug! Vielen Dank. Jetzt habe ich eine Frage zum Parsen der Ausgabe, die eine lange Reihe von Nicht-ASCII-Zeichen enthält, aber ich werde dies in einer separaten Frage stellen.
Barnabe
3
sollte nicht auf den 'Wert' gemäß stackoverflow.com/questions/2616659/… zugegriffen werden . Wie funktioniert der obige Code in diesem Fall? Ich dachte, Sie müssten auf den Wert zugreifen, indem Sieoutput = inputTag[0].contents
Seth
@Seth - nein, weil er nach dem Attribut 'value' des Eingabe-Tags sucht und .contents den vom Tag eingekapselten Text zurückgibt (<span> Ich bin .contents </ span>) - (antworte jetzt nur, weil ich es getan habe um zu überprüfen, was los war; jemand anderes könnte davon profitieren)
Dolan Antenucci
1
gute Antwort. Ich würde jedoch inputTag[0].get('value') stattdessen verwenden inputTag[0]['value'], um keinen Zeiger zu verhindern, falls das Tag kein
Wertattribut ist
Was ist mit Links, die nicht direkt mit der Homepage der besuchenden Website verknüpft sind? Wie erhalte ich alle Links, unabhängig davon, ob sie direkt oder indirekt mit der Webseite verknüpft sind?
Rink16
26

In Python 3.x, verwenden Sie einfach get(attr_name)auf das Tag - Objekt , das Sie erhalten , mit 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)

gegen XML-Datei conf//test1.xml, die aussieht wie:

<?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>

Drucke:

Processing repElem...
Attribute id = 11
Attribute name = Joe
Processing repElem...
Attribute id = 12
Attribute name = Mary
amphibient
quelle
Würde es Ihnen etwas ausmachen, wenn ich dies bearbeite, um PEP 8 zu folgen und die moderneren Methoden zur Formatierung von Zeichenfolgen zu verwenden?
AMC
Das ist in Ordnung, machen Sie es
Amphibient
6

Wenn Sie mehrere Werte von Attributen aus der obigen Quelle abrufen möchten, können Sie mithilfe findAlleines Listenverständnisses alles erhalten, was Sie benötigen:

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
quelle
4

Ich würde Ihnen tatsächlich einen zeitsparenden Weg vorschlagen, vorausgesetzt, Sie wissen, welche Art von Tags diese Attribute haben.

Angenommen, ein Tag xyz hat das Attritube mit dem Namen "stackinfo".

full_tag = soup.findAll("xyz")

Und ich möchte nicht, dass Sie verstehen, dass full_tag eine Liste ist

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

Somit können Sie alle attrb-Werte von Staininfo für alle Tags xyz abrufen

b1tchacked
quelle
3

Sie können dies auch verwenden:

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)
Mr.Bones
quelle
Wie unterscheidet sich das von den viel älteren Antworten, die schon hier waren?
AMC
0

Ich verwende dies mit Beautifulsoup 4.8.1, um den Wert aller Klassenattribute bestimmter Elemente zu erhalten:

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])

Es ist wichtig zu beachten, dass der Attributschlüssel eine Liste abruft, auch wenn das Attribut nur einen einzigen Wert hat.

PeterXX
quelle