Mengekstrak nilai atribut dengan beautifulsoup

112

Saya mencoba mengekstrak konten dari atribut "nilai" tunggal dalam tag "masukan" tertentu pada halaman web. Saya menggunakan kode berikut:

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)

Saya mendapatkan TypeError: indeks daftar harus berupa bilangan bulat, bukan str

Meskipun dari dokumentasi Beautifulsoup saya mengerti bahwa string seharusnya tidak menjadi masalah di sini ... tetapi saya bukan spesialis dan saya mungkin salah paham.

Setiap saran sangat dihargai! Terima kasih sebelumnya.

Barnabe
sumber

Jawaban:

150

.find_all() mengembalikan daftar semua elemen yang ditemukan, jadi:

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

input_tagadalah daftar (mungkin hanya berisi satu elemen). Bergantung pada apa yang Anda inginkan, Anda harus melakukan:

 output = input_tag[0]['value']

atau gunakan .find()metode yang hanya mengembalikan satu elemen (pertama) yang ditemukan:

 input_tag = soup.find(attrs={"name": "stainfo"})
 output = input_tag['value']
Łukasz
sumber
Barang bagus! Terima kasih. sekarang saya punya pertanyaan tentang parsing output yang merupakan sekelompok panjang karakter non-ASCII tetapi saya akan menanyakan ini dalam pertanyaan terpisah.
Barnabe
3
seharusnya 'nilai' diakses sesuai stackoverflow.com/questions/2616659/… . Apa yang membuat kode di atas berfungsi dalam kasus ini? Saya pikir Anda harus mengakses nilai dengan melakukanoutput = inputTag[0].contents
Set
@ Set - tidak, karena dia sedang mencari 'nilai' atribut input-tag, dan .contents mengembalikan teks yang dienkapsulasi oleh tag (<span> Saya. Konten </span>) - (hanya membalas sekarang karena saya punya untuk memeriksa ulang apa yang sedang terjadi; mencari tahu orang lain mungkin mendapat manfaat)
Dolan Antenucci
1
jawaban yang bagus. Namun, saya akan menggunakaninputTag[0].get('value') alih-alih inputTag[0]['value']untuk mencegah tidak ada penunjuk jika tag tidak memiliki atribut nilai
amfibi
Bagaimana dengan link yang tidak langsung terhubung ke homepage situs yang mengunjungi, Bagaimana cara mendapatkan semua link baik yang tertaut ke halaman web secara langsung maupun tidak langsung.
Rink16
26

Di Python 3.x, cukup gunakan get(attr_name)pada objek tag yang Anda gunakan 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)

terhadap file XML conf//test1.xmlyang terlihat seperti:

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

cetakan:

Processing repElem...
Attribute id = 11
Attribute name = Joe
Processing repElem...
Attribute id = 12
Attribute name = Mary
amfibi
sumber
Apakah Anda keberatan jika saya mengedit ini untuk mengikuti PEP 8 dan menggunakan metode pemformatan string yang lebih modern?
AMC
Tidak apa-apa, lakukan saja
amfibi
6

Jika Anda ingin mengambil beberapa nilai atribut dari sumber di atas, Anda dapat menggunakan findAlldan pemahaman daftar untuk mendapatkan semua yang Anda butuhkan:

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

Saya sebenarnya menyarankan Anda untuk menghemat waktu dengan asumsi ini bahwa Anda tahu jenis tag yang memiliki atribut tersebut.

misalkan tag xyz memiliki attritube bernama "staininfo" ..

full_tag = soup.findAll("xyz")

Dan saya tidak ingin Anda memahami bahwa full_tag adalah daftar

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

Dengan demikian Anda bisa mendapatkan semua nilai attrb dari staininfo untuk semua tag xyz

b1tchacked
sumber
3

Anda juga bisa menggunakan ini:

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)
Tuan Tulang
sumber
Bagaimana ini berbeda dari jawaban yang jauh lebih tua yang sudah ada di sini?
AMC
0

Saya menggunakan ini dengan Beautifulsoup 4.8.1 untuk mendapatkan nilai semua atribut kelas dari elemen tertentu:

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

Penting untuk diperhatikan bahwa kunci atribut mengambil daftar bahkan ketika atribut hanya memiliki satu nilai.

PeterXX
sumber