कक्षा द्वारा तत्वों को कैसे खोजना है


386

मुझे सुंदर वर्ग का उपयोग करके "वर्ग" विशेषता वाले HTML तत्वों को पार्स करने में समस्या हो रही है। कोड इस तरह दिखता है

soup = BeautifulSoup(sdata)
mydivs = soup.findAll('div')
for div in mydivs: 
    if (div["class"] == "stylelistrow"):
        print div

मुझे स्क्रिप्ट खत्म होने के बाद उसी लाइन पर "त्रुटि" मिलती है।

File "./beautifulcoding.py", line 130, in getlanguage
  if (div["class"] == "stylelistrow"):
File "/usr/local/lib/python2.6/dist-packages/BeautifulSoup.py", line 599, in __getitem__
   return self._getAttrMap()[key]
KeyError: 'class'

मैं इस त्रुटि से कैसे छुटकारा पाऊं?

जवाबों:


646

आप अपनी खोज को केवल उन विभाजनों को खोज सकते हैं जो बीएस 3 का उपयोग करके दिए गए वर्ग के साथ करते हैं:

mydivs = soup.findAll("div", {"class": "stylelistrow"})

@ क्लॉस- अगर मैं इसके बजाय findAll का उपयोग करना चाहता हूं?

1
इसके लिए धन्यवाद। यह सिर्फ @class के लिए नहीं बल्कि किसी भी चीज के लिए है।
प्रागीथ

41
यह केवल सटीक मैचों के लिए काम करता है। <.. class="stylelistrow">मेल खाता है लेकिन नहीं <.. class="stylelistrow button">
वर्नट

4
@pyCthon @jmunsch के लिए उत्तर देखें, बीएस अब समर्थन करता है class_जो ठीक से काम करता है।
9

25
Beautifulsoup4 के रूप में, findAll अब find_all है
Neoecos

273

प्रलेखन से:

सुंदर सूप 4.1.2 के रूप में, आप कीवर्ड तर्क का उपयोग करके CSS वर्ग द्वारा खोज सकते हैं class_ :

soup.find_all("a", class_="sister")

इस मामले में कौन सा होगा:

soup.find_all("div", class_="stylelistrow")

यह भी काम करेगा:

soup.find_all("div", class_="stylelistrowone stylelistrowtwo")

5
आप सूचियों का भी उपयोग कर सकते हैं: soup.find_all("a", ["stylelistrowone", "stylelistrow"])यदि आपके पास कई कक्षाएं नहीं हैं तो यह अधिक सुरक्षित है।
नूनो एंड्रे

4
यह स्वीकृत उत्तर होना चाहिए, यह विकल्पों की तुलना में अधिक सही और संक्षिप्त दोनों है।
गॉनकॉल्प

1
BeautifulSoup 3 के लिए @ NunoAndré के उत्तर के लिए अनुपूरक soup.findAll("a", {'class':['stylelistrowone', 'stylelistrow']}):।
ब्रैड


18

BeautifulSoup 3 के लिए विशिष्ट:

soup.findAll('div',
             {'class': lambda x: x 
                       and 'stylelistrow' in x.split()
             }
            )

इन सभी को मिलेगा:

<div class="stylelistrow">
<div class="stylelistrow button">
<div class="button stylelistrow">

पुनः खोज क्यों नहीं की जाती ('*। स्टाइलिस्ट्रो। *', X)?
rjurney

क्योंकि तब स्टाइलिस्ट्रो 2 का मिलान होगा। बेहतर टिप्पणी है "पुनः के बजाय string.find () का उपयोग क्यों नहीं किया जाता है?"
FlipMcF

2
lambda x: 'stylelistrow' in x.split()सरल और सुंदर है
fferri

और मैं regexes से नफरत है। धन्यवाद! (अद्यतन उत्तर) | - x ’और
नो

16

एक सीधा आगे रास्ता होगा:

soup = BeautifulSoup(sdata)
for each_div in soup.findAll('div',{'class':'stylelist'}):
    print each_div

सुनिश्चित करें कि आप का आवरण के ले findAll अपनी नहीं, findall


4
यह केवल सटीक मैचों के लिए काम करता है। <.. class="stylelistrow">मेल खाता है लेकिन नहीं <.. class="stylelistrow button">
वर्नट

11

कक्षा द्वारा तत्वों को कैसे खोजना है

मुझे सुंदर वर्ग का उपयोग करके "क्लास" विशेषता वाले HTML तत्वों को पार्स करने में समस्या हो रही है।

आप आसानी से एक वर्ग द्वारा पा सकते हैं, लेकिन यदि आप दो वर्गों के प्रतिच्छेदन द्वारा खोजना चाहते हैं, तो यह थोड़ा और कठिन है,

से प्रलेखन (जोर जोड़ा):

यदि आप दो या अधिक सीएसएस वर्गों से मेल खाने वाले टैग की खोज करना चाहते हैं, तो आपको एक सीएसएस चयनकर्ता का उपयोग करना चाहिए:

css_soup.select("p.strikeout.body")
# [<p class="body strikeout"></p>]

स्पष्ट होने के लिए, यह केवल उन पी टैग्स का चयन करता है जो स्ट्राइकआउट और बॉडी क्लास दोनों हैं।

वर्गों के एक समूह में किसी भी चौराहे को खोजने के लिए (चौराहा नहीं, बल्कि संघ), आप class_कीवर्ड तर्क को एक सूची दे सकते हैं (4.1.2 के रूप में):

soup = BeautifulSoup(sdata)
class_list = ["stylelistrow"] # can add any other classes to this list.
# will find any divs with any names in class_list:
mydivs = soup.find_all('div', class_=class_list) 

यह भी ध्यान दें कि findAll का नाम बदलकर कैमलकेस से अधिक पाइथोनिक कर दिया गया है find_all


11

सीएसएस चयनकर्ताओं

एकल वर्ग का पहला मैच

soup.select_one('.stylelistrow')

मैचों की सूची

soup.select('.stylelistrow')

यौगिक वर्ग (यानी और अन्य वर्ग)

soup.select_one('.stylelistrow.otherclassname')
soup.select('.stylelistrow.otherclassname')

मिश्रित वर्ग के नामों में रिक्त स्थान जैसे class = stylelistrow otherclassname""। आप कक्षाएं जोड़ना जारी रख सकते हैं।

कक्षाओं की सूची (या - जो भी मौजूद हो मेल करें

soup.select_one('.stylelistrow, .otherclassname')
soup.select('.stylelistrow, .otherclassname')

bs4 4.7.1 +

विशिष्ट वर्ग जिसका innerTextएक तार होता है

soup.select_one('.stylelistrow:contains("some string")')
soup.select('.stylelistrow:contains("some string")')

विशिष्ट वर्ग जिसमें एक निश्चित बाल तत्व होता है जैसे aटैग

soup.select_one('.stylelistrow:has(a)')
soup.select('.stylelistrow:has(a)')

5

ब्यूटीफुल 4+ के रूप में,

यदि आपके पास एकल वर्ग का नाम है, तो आप कक्षा के नाम को पैरामीटर के रूप में पास कर सकते हैं:

mydivs = soup.find_all('div', 'class_name')

या यदि आपके पास एक से अधिक वर्ग नाम हैं, तो कक्षा के नामों की सूची को पैरामीटर की तरह पास करें:

mydivs = soup.find_all('div', ['class1', 'class2'])

3

यह जाँचने की कोशिश करें कि div के पास पहले एक वर्गीय विशेषता है, जैसे:

soup = BeautifulSoup(sdata)
mydivs = soup.findAll('div')
for div in mydivs:
    if "class" in div:
        if (div["class"]=="stylelistrow"):
            print div

1
यह काम नहीं करता है। मुझे लगता है कि आपका दृष्टिकोण सही था, लेकिन 4 वीं पंक्ति काम नहीं करती है।
नव

1
आह मुझे लगा कि डिव ने एक डिक्शनरी की तरह काम किया है, मैं सुंदर सूप से वास्तव में परिचित नहीं हूं इसलिए यह सिर्फ एक अनुमान था।
मेव

3

यह मेरे लिए वर्ग विशेषता तक पहुंच बनाने के लिए काम करता है (beautifulsoup 4 पर, इसके विपरीत जो प्रलेखन कहता है)। KeyError एक सूची आती है जिसे एक शब्दकोश नहीं दिया जाता है।

for hit in soup.findAll(name='span'):
    print hit.contents[1]['class']



1

वैकल्पिक रूप से हम lxml का उपयोग कर सकते हैं, यह xpath और बहुत तेजी से समर्थन करता है!

from lxml import html, etree 

attr = html.fromstring(html_text)#passing the raw html
handles = attr.xpath('//div[@class="stylelistrow"]')#xpath exresssion to find that specific class

for each in handles:
    print(etree.tostring(each))#printing the html as string

0

यह काम करना चाहिए:

soup = BeautifulSoup(sdata)
mydivs = soup.findAll('div')
for div in mydivs: 
    if (div.find(class_ == "stylelistrow"):
        print div

0

अन्य उत्तर मेरे काम नहीं आए।

अन्य उत्तरों में findAllसूप ऑब्जेक्ट पर ही उपयोग किया जा रहा है, लेकिन मुझे एक ऐसा तरीका चाहिए था जिसे करने के बाद प्राप्त की गई वस्तु से निकाले गए एक विशिष्ट तत्व के अंदर वस्तुओं पर वर्ग नाम से एक खोज करना findAll

यदि आप वर्ग नाम से ऑब्जेक्ट प्राप्त करने के लिए नेस्टेड HTML तत्वों के अंदर एक खोज करने की कोशिश कर रहे हैं, तो नीचे देखें -

# parse html
page_soup = soup(web_page.read(), "html.parser")

# filter out items matching class name
all_songs = page_soup.findAll("li", "song_item")

# traverse through all_songs
for song in all_songs:

    # get text out of span element matching class 'song_name'
    # doing a 'find' by class name within a specific song element taken out of 'all_songs' collection
    song.find("span", "song_name").text

नोट करने के लिए अंक:

  1. मैं स्पष्ट रूप से खोज को 'क्लास' विशेषता पर परिभाषित नहीं कर रहा हूं findAll("li", {"class": "song_item"}), क्योंकि यह एकमात्र ऐसी विशेषता है जिस पर मैं खोज कर रहा हूं और यह क्लास विशेषता के लिए डिफ़ॉल्ट खोज करेगा यदि आप विशेष रूप से यह नहीं बताते हैं कि आप किस विशेषता को खोजना चाहते हैं।

  2. जब आप findAllया करते हैं find, तो परिणामी वस्तु वर्ग की bs4.element.ResultSetहोती है जो कि उपवर्ग होती है list। आप सभी तरीकों का उपयोग कर सकते हैं ResultSet, किसी भी संख्या में नेस्टेड तत्वों के अंदर (जब तक वे प्रकार के होते हैं ResultSet) सभी को खोजने या खोजने के लिए।

  3. मेरा बीएस 4 संस्करण - 4.9.1, पायथन संस्करण - 3.8.1


0

निम्नलिखित काम करना चाहिए

soup.find('span', attrs={'class':'totalcount'})

अपने वर्ग के नाम के साथ 'टोटकाउंट' और 'स्पैन' को टैग के साथ बदलें। इसके अलावा, यदि आपकी कक्षा में स्थान के साथ कई नाम हैं, तो बस एक चुनें और उपयोग करें।

पुनश्च यह दिए गए मानदंडों के साथ पहला तत्व पाता है। यदि आप सभी तत्वों को खोजना चाहते हैं, तो 'find' को 'find_all' से बदलें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.