Extraindo um valor de atributo com beautifulsoup


110

Estou tentando extrair o conteúdo de um único atributo "valor" em uma tag "entrada" específica em uma página da web. Eu uso o seguinte 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)

Recebo um TypeError: os índices da lista devem ser inteiros, não str

Embora a partir da documentação do Beautifulsoup eu entenda que as strings não devem ser um problema aqui ... mas não sou nenhum especialista e posso ter entendido mal.

Qualquer sugestão é muito apreciada! Desde já, obrigado.

Respostas:


147

.find_all() retorna a lista de todos os elementos encontrados, então:

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

input_tagé uma lista (provavelmente contendo apenas um elemento). Dependendo do que você deseja exatamente, você deve fazer:

 output = input_tag[0]['value']

ou use o .find()método que retorna apenas um (primeiro) elemento encontrado:

 input_tag = soup.find(attrs={"name": "stainfo"})
 output = input_tag['value']

Coisas boas! Obrigado. agora eu tenho uma pergunta sobre como analisar a saída, que é um monte de caracteres não ASCII, mas vou fazer isso em uma pergunta separada.
Barnabe de

3
o 'valor' não deveria ser acessado conforme stackoverflow.com/questions/2616659/… . O que faz o código acima funcionar neste caso? Achei que você teria que acessar o valor fazendooutput = inputTag[0].contents
Set,

@Seth - não, porque ele está procurando o 'valor' de atributo da tag de entrada, e .contents retorna o texto encapsulado pela tag (<span> eu sou .contents </span>) - (apenas respondendo agora porque eu tinha para verificar o que estava acontecendo; descobrir que outra pessoa pode se beneficiar)
Dolan Antenucci

1
Ótima resposta. no entanto, eu usaria em inputTag[0].get('value') vez de inputTag[0]['value']para evitar nenhum ponteiro no caso da tag como nenhum atributo de valor
anfibiente

e quanto aos links que não estão diretamente ligados à página inicial do site visitado, Como obter todos os links, sejam eles vinculados à página da web direta ou indiretamente.
Rink16

26

Em Python 3.x, basta usar get(attr_name)em seu objeto tag que você obtém 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 um arquivo XML conf//test1.xmlque se parece com:

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

estampas:

Processing repElem...
Attribute id = 11
Attribute name = Joe
Processing repElem...
Attribute id = 12
Attribute name = Mary

Você se importaria se eu editar isso para seguir o PEP 8 e usar os métodos de formatação de string mais modernos?
AMC

Tudo bem, vá em frente
anfibiente de

6

Se você deseja recuperar vários valores de atributos da fonte acima, você pode usar findAlluma compreensão de lista para obter tudo que você precisa:

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.

4

Na verdade, eu sugeriria uma maneira de economizar tempo para fazer isso, supondo que você saiba que tipo de tag tem esses atributos.

suponha que uma tag xyz tenha esse attritube chamado "staininfo".

full_tag = soup.findAll("xyz")

E eu quero que você entenda que full_tag é uma lista

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

Assim você pode obter todos os valores de atributo de staininfo para todas as marcas xyz


3

você também pode usar isto:

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)

Como isso difere das respostas muito mais antigas que já estavam aqui?
AMC

0

Estou usando isso com Beautifulsoup 4.8.1 para obter o valor de todos os atributos de classe de certos 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])

É importante observar que a chave do atributo recupera uma lista mesmo quando o atributo tem apenas um único valor.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.