Я пытаюсь идентифицировать элементы DOM по имени класса, но я не могу использовать pattern.web, как описано в документах (я также запускаю код, который я использовал раньше, поэтому он работал в какой-то момент).
from pattern.web import DOM
html = """<html><head><title>pattern.web | CLiPS</title></head>
<body>
<div class="class1 class2 class3">
<form action="/pages/pattern-web" accept-charset="UTF-8" method="post" id="search-block-form">
<div>
<label for="edit-search-block-form-1">Search this site: </label>
</div>
</form>
</div>
</body></html>"""
dom = DOM(html)
print "Search Results by Method:"
print 'tag[attr="value"] Notation Results:'
print dom('div[class="class1 class2 class3"]')
print
print 'tag.class Notation Results:'
print dom('div.class1')
print
print 'By class, no tag results:'
print dom.by_class('class1')
print
print 'Looping through all divs and printing matching results:'
for i in dom('div'):
if 'class' in i.attrs and i.attrs['class'] == 'class1 class2 class3':
print i.attrs
Обратите внимание, что (функции Element
и DOM
взаимозаменяемы и дают одинаковые результаты). В результате получается следующее:
Search Results by Method:
tag[attr="value"] Notation Results:
[]
tag.class Notation Results:
[]
By class, no tag results:
[Element(tag='div')]
Looping through all divs and printing matching results:
{u'class': u'class1 class2 class3'}
Как вы можете видеть, поиск с использованием tag.class
и tag[attr="value"]
дают пустые результаты, но by_class
возвращает один результат. Ясно, что существуют элементы с этими атрибутами. Как искать все div, которые имеют все 3 класса?
Раньше я мог искать с помощью dom('div.class1.class2.class3')
чтобы идентифицировать div со всеми 3 классами. Это не только не работает, но и дает мне unicode-ошибки (кажется, что второй период вызывает ошибку Unicode): TypeError: descriptor 'lower' requires a 'str' object but received a 'unicode'
Вопрос: В прошлом я смог выполнить поиск с помощью
dom('div.class1.class2.class3')
чтобы идентифицировать div со всеми 3 классами.
Чтение источника github.com/clips/pattern/blob/master/pattern/web,
нашел, это только обертка с использованиемBeautiful Soup
.# Beautiful Soup завернут в классы DOM, Element и Text, похожие на Javascript DOM.
# Красивый суп также можно использовать напрямую
Это известный вопрос, см. SO: Beautiful soup find_all не находит селектор CSS с несколькими классами
Обходной путь ist использовать .select(...)
вместо .find_all(...)
,
не нашел. .select(...)
в pattern.web
Например:
from bs4 import BeautifulSoup
html = """<html><head><title>pattern.web | CLiPS</title></head>
<body>
<div class="class1 class4">
<form action="/pages/pattern-web" accept-charset="UTF-8" method="post" id="search-block-form">
<div class="class1 class2 class3">
<label for="edit-search-block-form-1">Search this site: </label>
</div>
</form>
</div>
</body></html>
"""
soup = BeautifulSoup(html, 'html.parser')
div = soup.select('div.class1.class2')
print("{}".format(div))
Выход:
[<div class="class1 class2 class3"> <label for="edit-search-block-form-1">Search this site: </label> </div>]
Вопрос: он также дает мне ошибки в Unicode (кажется, что второй период вызывает ошибку Unicode):
TypeError: descriptor 'lower' requires a 'str' object but received a 'unicode'
Это неизвестно, если этот TypeError
является pattern.web
или Beautiful Soup
.
Согласно этому SO: дескриптору-join-require-a-unicode-object-but-received-a-str это стандартное сообщение Python.
Используя pattern.web
из GitHub, результаты ожидаются:
from pattern.web import Element
elements = Element(html)
print("Search Results by Method:")
print('tag[attr="value"] Notation\tResults:{}'
.format(elements('div[class="class1 class2 class3"]')))
print('tag.class Notation \t\t\tResults:{}'
.format(elements('div.class1.class2.class3')))
print('By class, no tag \t\t\tResults:{}'
.format(elements.by_class('class1 class2 class3')))
print('Looping through all divs and printing matching results:')
for i in elements('div'):
if 'class' in i.attrs:
if " ".join(i.attrs['class']) == 'class1 class2 class3':
print("\tmatch:{}".format(i.attrs))
Выход:
Search Results by Method: tag[attr="value"] Notation Results:{'class': ['class1', 'class2', 'class3']} tag.class Notation Results:{'class': ['class1', 'class2', 'class3']} By class, no tag Results:{'class': ['class1', 'class2', 'class3']} Looping through all divs and printing matching results: match:{'class': ['class1', 'class2', 'class3']}
Протестировано с помощью Python: 3.5.3 - pattern.web: 3.6 - bs4: 4.5.3
pattern.web
из GitHub, я получил результаты, как и ожидалось. Ваша TypeError
зависит от версии.