Python & Beautifulsoup 4 - Невозможно отфильтровать классы? - PullRequest
2 голосов
/ 26 марта 2019

Я пытаюсь вычистить размеры обуви по этому URL: http://www.jimmyjazz.com/mens/footwear/jordan-retro-13--atmosphere-grey-/414571-016?color=Grey

Я пытаюсь получить только доступные размеры, например, только те, которые не выделены серым цветом.

Все размеры заключены в a элементы.Доступные размеры относятся к классу box, а недоступные - к классу box piunavailable.

Я пробовал использовать лямбда-функции, ifs и CSS-селекторы - ни один из них не работает.Я думаю, это из-за того, как мой код структурирован.

Он структурирован следующим образом:

if попытка

size = soup2.find('div', attrs={'class': 'psizeoptioncontainer'})
getsize = str([e.get_text() for e in size.findAll('a', attrs={'class': 'box'}) if 'piunavailable' not in e.attrs['class']])

Лямбда-попытка

size = soup2.find('div', attrs={'class': 'psizeoptioncontainer'})
getsize = str([e.get_text() for e in size.findAll(lambda tag: tag.name == 'a' and tag.get('class') == ['box piunavailable'])])

Попытка селектора CSS

size = soup2.find('div', attrs={'class': 'psizeoptioncontainer'})
getsize = str([e.get_text() for e in size.findAll('a[class="box"]'))

Итак, для предоставленного URL я ожидаю, что результатом будет строка (преобразованная из списка) всех доступных размеров - навремя написания этого вопроса, это должно быть - '8', '8.5', '9', '9.5', '10', '10.5', '11', '11.5', '13'

Вместо этого я получаю все размеры, '7.5', '8', '8.5', '9', '9.5', '10', '10.5', '11', '11.5', '12', '13'

У кого-нибудь есть идея, как заставить это работать (или знатьэлегантное решение моей проблемы)?Заранее спасибо!

Ответы [ 2 ]

1 голос
/ 27 марта 2019

Требуется, чтобы псевдо-класс селектора css : не исключал другой класс.Использование bs4 4.7.1.

sizes = [item.text for item in soup.select('.box:not(.piunavailable)')]

В полном объеме:

import requests
from bs4 import BeautifulSoup

r = requests.get('http://www.jimmyjazz.com/mens/footwear/jordan-retro-13--atmosphere-grey-/414571-016?color=Grey')  
soup = BeautifulSoup(r.content,'lxml')  
sizes = [item.text for item in soup.select('.box:not(.piunavailable)')]
print(sizes)
1 голос
/ 26 марта 2019

То, что вы просите, - это получить теги a с определенным классом box и без других классов. Это может быть выполнено через , передавая пользовательскую функцию в качестве фильтра в find_all .

def my_match_function(elem):
 if isinstance(elem,Tag) and elem.name=='a' and ''.join(elem.attrs.get('class',''))=='box':
     return True

Здесь ''.join(elem.attrs.get('class',''))=='box' гарантирует, что тег a имеет только класс box и никакого другого класса.

Давайте посмотрим на это в действии

from bs4 import BeautifulSoup,Tag
html="""
<a>This is also not needed.</a>
<div class="box_wrapper">
<a id="itemcode_11398535" class="box piunavailable">7.5</a>
<a href="#" id="itemcode_11398536" class="box">8</a>
<a href="#" id="itemcode_11398537" class="box">8.5</a>
<a href="#" id="itemcode_11398538" class="box">9</a>
<a href="#" id="itemcode_11398539" class="box">9.5</a>
<a href="#" id="itemcode_11398540" class="box">10</a>
<a href="#" id="itemcode_11398541" class="box">10.5</a>
<a href="#" id="itemcode_11398542" class="box">11</a>
<a href="#" id="itemcode_11398543" class="box">11.5</a>
<a id="itemcode_11398544" class="box piunavailable">12</a>
<a href="#" id="itemcode_11398545" class="box">13</a>
</div>
"""
def my_match_function(elem):
 if isinstance(elem,Tag) and elem.name=='a' and ''.join(elem.attrs.get('class',''))=='box':
     return True
soup=BeautifulSoup(html,'html.parser')
my_list=[x.text for x in soup.find_all(my_match_function)]
print(my_list)

Выходы:

['8', '8.5', '9', '9.5', '10', '10.5', '11', '11.5', '13']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...