Шаблон сети не может найти элементы по именам классов

1

Я пытаюсь идентифицировать элементы 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'

  • 0
    Я попробовал это на самом деле, они ведут себя одинаково / не имеет значения. Я начинаю думать, что последняя версия pattern.web не поддерживает поиск по нескольким именам классов.
  • 0
    Реальные данные будут однозначно идентифицировать, я не могу этого сделать @stovfl. Я поделился реальными данными, которые просто заменили на анонимные.
Показать ещё 4 комментария
Теги:
python-pattern

1 ответ

0
Лучший ответ

Вопрос: В прошлом я смог выполнить поиск с помощью 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

  • 0
    Очень полезно, спасибо. Я не знал, что pattern.web был построен поверх него, он был представлен мне как альтернатива!
  • 0
    @ Пользователь: обновил мой ответ, используя pattern.web из GitHub, я получил результаты, как и ожидалось. Ваша TypeError зависит от версии.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню