I want to print data from a div with a class value but my code keeps returning additional data from another similar div

Viewed 104

Here's the HTML code:

<div class="sizeBlock">
 <div class="size"> 
    <a class="selectSize" id="44526" data-size-original="36.5">36.5</a> 
 </div> 
 <div class="size inactive active"> 
    <a class="selectSize" id="44524" data-size-original="40">40</a> 
 </div> 
 <div class="size"> 
    <a class="selectSize" id="44525" data-size-original="40.5">40.5</a> 
 </div> 
</div>

I want to get the values of the id tag and the data-size-original inside <div class="size"> only.

Here's my code:

for sizeBlock in soup.select('div.size a.selectSize'):
aid = sizeBlock.get('id')
size = sizeBlock.get('data-size-original')
print(aid, size)

The problem is that it also returns the data from <div class="size inactive active">

Here's a picture of the execution of the code

3 Answers
from bs4 import BeautifulSoup


html_doc = """<div class="sizeBlock">
 <div class="size"> 
    <a class="selectSize" id="44526" data-size-original="36.5">36.5</a> 
 </div> 
 <div class="size inactive active"> 
    <a class="selectSize" id="44524" data-size-original="40">40</a> 
 </div> 
 <div class="size"> 
    <a class="selectSize" id="44525" data-size-original="40.5">40.5</a> 
 </div> 
</div>"""  


soup = BeautifulSoup(html_doc)
for sizeBlock in soup.select('div.size'):
    if sizeBlock.get('class') != ['size']:
        continue
    soup2 = sizeBlock.select('a.selectSize')[0]
    aid = soup2.get('id')
    size = soup2.get('data-size-original')
    print(aid, size)

Output:

44526 36.5
44525 40.5

Explanation:

if sizeBlock.get('class') != ['size']:
    continue

Will skip over any class that is not 'size' != is the not equal to operator. Since for the 'size inactive active' class get('class') returns ['size', 'inactive', 'active'] this block is passed over in the loop.

sizeBlock.select('a.selectSize')

returns a list

[<a class="selectSize" data-size-original="36.5" id="44526">36.5</a>]

and so writing

sizeBlock.select('a.selectSize')[0]

returns the first (and only) element of this list.

I think you could go with a more succinct method using a class attribute selector (by using as attribute selector you can limit to parent div with single appropriate class) and generate a dictionary:

from bs4 import BeautifulSoup as bs
import requests

html = '''<div class="sizeBlock">
 <div class="size"> 
    <a class="selectSize" id="44526" data-size-original="36.5">36.5</a> 
 </div> 
 <div class="size inactive active"> 
    <a class="selectSize" id="44524" data-size-original="40">40</a> 
 </div> 
 <div class="size"> 
    <a class="selectSize" id="44525" data-size-original="40.5">40.5</a> 
 </div> 
</div>'''

soup = bs(html, 'lxml')
d = {i['id']:i['data-size-original'] for i in soup.select('[class=size] a')}
print(d)

Adjust dict comprehension to loop if you want to store in variables

for i in soup.select('[class=size] a'):
    aid = i['id'];size = i['data-size-original'] 
    print(aid, size)

You can implement the functionality as below.

soup = BeautifulSoup(html_doc, 'html.parser')
all_a = soup.find_all('a')
for a in all_a:
    aid = a.get('id')
    size = a.get('data-size-original')
    print(aid, size)
Related