Extraer un valor de atributo con beautifulsoup

110

Estoy tratando de extraer el contenido de un atributo de "valor" único en una etiqueta de "entrada" específica en una página web. Yo uso el siguiente código:

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)

Obtengo un TypeError: los índices de lista deben ser enteros, no str

a pesar de que de la documentación de Beautifulsoup entiendo que las cadenas no deberían ser un problema aquí ... pero no soy un especialista y puede que lo haya entendido mal.

¡Cualquier sugerencia sera grandemente apreciada! Gracias por adelantado.

Bernabé
fuente

Respuestas:

148

.find_all() devuelve una lista de todos los elementos encontrados, así que:

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

input_tages una lista (probablemente contenga solo un elemento). Dependiendo de lo que desee exactamente, debe hacer:

 output = input_tag[0]['value']

o use el .find()método que devuelve solo un (primer) elemento encontrado:

 input_tag = soup.find(attrs={"name": "stainfo"})
 output = input_tag['value']
Łukasz
fuente
¡Buena cosa! Gracias. ahora tengo una pregunta sobre el análisis de la salida, que es un grupo largo de caracteres no ASCII, pero lo haré en una pregunta separada.
Barnabe
3
¿No se debe acceder al 'valor' según stackoverflow.com/questions/2616659/… . ¿Qué hace que el código anterior funcione en este caso? Pensé que tendrías que acceder al valor haciendooutput = inputTag[0].contents
Seth
@Seth - no, porque está buscando el atributo 'valor' de la etiqueta de entrada, y .contents devuelve el texto encapsulado por la etiqueta (<span> Soy .contents </span>) - (solo respondiendo ahora porque tenía para verificar lo que estaba pasando; imagino que alguien más podría beneficiarse)
Dolan Antenucci
1
gran respuesta. sin embargo, usaría en inputTag[0].get('value') lugar de inputTag[0]['value']evitar ningún puntero en caso de que la etiqueta no
tenga un
¿Qué pasa con los enlaces que no están directamente vinculados a la página de inicio del sitio web que visita? Cómo obtener todos los enlaces, ya sea que estén vinculados a la página web directa o indirectamente.
Pista 16 de
26

En Python 3.x, simplemente use get(attr_name)en su objeto de etiqueta que obtiene usando 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)

contra un archivo XML conf//test1.xmlque se parece a:

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

huellas dactilares:

Processing repElem...
Attribute id = 11
Attribute name = Joe
Processing repElem...
Attribute id = 12
Attribute name = Mary
anfibio
fuente
¿Le importaría si edito esto para seguir PEP 8 y ​​usar los métodos de formato de cadena más modernos?
AMC
Está bien, adelante
anfibio
6

Si desea recuperar múltiples valores de atributos de la fuente anterior, puede usar findAlluna lista de comprensión para obtener todo lo que necesita:

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

De hecho, le sugeriría una forma de ahorrar tiempo asumiendo que sabe qué tipo de etiquetas tienen esos atributos.

supongamos que una etiqueta xyz tiene ese atributo llamado "staininfo".

full_tag = soup.findAll("xyz")

Y no quiero que entiendas que full_tag es una lista

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

Por lo tanto, puede obtener todos los valores attrb de staininfo para todas las etiquetas xyz

b1tchacked
fuente
3

también puedes usar esto:

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)
Señor huesos
fuente
¿En qué se diferencia esto de las respuestas mucho más antiguas que ya estaban aquí?
AMC
0

Estoy usando esto con Beautifulsoup 4.8.1 para obtener el valor de todos los atributos de clase de ciertos elementos:

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 importante tener en cuenta que la clave de atributo recupera una lista incluso cuando el atributo tiene un solo valor.

PeterXX
fuente