Как я могу сопоставить одинарные и двойные атрибуты HTML в регулярном выражении? - PullRequest
0 голосов
/ 07 июля 2019

У меня есть элемент HTML с двумя разными классами. но в некоторых случаях у меня есть только один класс. Когда есть два класса, они разделяются пробелом.

"rating-inbtn hide-if-zero-113"
 or 
"rating-inbtn"

Как мне сопоставить оба шаблона в регулярном выражении.

Для справки я хочу поставить мой старый пост:

<span class="vote-actions">
    <a class="btn btn-default vote-action-good">
        <span class="icon thumb-up black black-hover">&nbsp;</span>
        <span class="rating-inbtn">215</span>
    </a>
    <a class="btn btn-default vote-action-bad">
        <span class="icon thumb-down grey black-hover">&nbsp;</span>
        <span class="rating-inbtn">82</span>
    </a>
</span>

и я использовал это регулярное выражение для извлечения оценок

a = re.findall('rating-inbtn">(.*?)</span>', webpage)
        like_count = a[0]
        dislike_count = a[1]

Но иногда класс span имеет более одного атрибута «hide-if-zero-113», в таком случае, как я могу обработать этот шаблон?

Спасибо

Ответы [ 3 ]

2 голосов
/ 07 июля 2019

Может быть, я что-то упускаю, но вам не нужны регулярные выражения для извлечения чисел из кода:

data = '''<span class="vote-actions">
    <a class="btn btn-default vote-action-good">
        <span class="icon thumb-up black black-hover">&nbsp;</span>
        <span class="rating-inbtn">215</span>
    </a>
    <a class="btn btn-default vote-action-bad">
        <span class="icon thumb-down grey black-hover">&nbsp;</span>
        <span class="rating-inbtn">82</span>
    </a>
</span>'''

from bs4 import BeautifulSoup

soup = BeautifulSoup(data, 'lxml')

print([span.text for span in soup.select('span.rating-inbtn')])

Печать:

['215', '82']
1 голос
/ 08 июля 2019

Я остановлюсь на одном из приведенных ответов.В ваших нижних примерах вы смотрите на два элемента, которые совместно используют один и тот же класс, которого должно быть достаточно, чтобы соответствовать обоим элементам.В вашем самом верхнем примере показан составной класс (более одного имени класса для элемента), но опять-таки он имеет тот же класс rating-inbtn.

soup.select('.rating-inbtn')

, где "."является селектором класса css.

Расширение на другие ответы:

В будущем вы можете передавать списки, разделенные символом ",", чтобы соответствовать более чем одному классу (более чем одному селектору), например

soup.select('.rating-inbtn, .otherClass') 
0 голосов
/ 07 июля 2019

Это зависит от границ, которые вы хотите добавить в выражение.Например, мы могли бы начать с:

\s*([a-z0-9-]+)(?:\s+)?([a-z0-9-]+)?\s*

Выражение объяснено на верхней правой панели этой демонстрации , если вы хотите изучить ее дальше или изменить, и в эту ссылку , вы можете посмотреть, как она будет шаг за шагом сопоставляться с некоторыми примерами входных данных, если хотите.


Редактировать:

Для получения этих оценок это выражениеможет просто хватить:

rating-inbtn[^>]+>\s*([^\s<]+)\s*<\/

Демо

Тест с re.findall

import re

regex = r"rating-inbtn[^>]+>\s*([^\s<]+)\s*<\/"

test_str = ("<span class=\"vote-actions\">\n"
    "    <a class=\"btn btn-default vote-action-good\">\n"
    "        <span class=\"icon thumb-up black black-hover\">&nbsp;</span>\n"
    "        <span class=\"rating-inbtn\">215</span>\n"
    "    </a>\n"
    "    <a class=\"btn btn-default vote-action-bad\">\n"
    "        <span class=\"icon thumb-down grey black-hover\">&nbsp;</span>\n"
    "        <span class=\"rating-inbtn\">82</span>\n"
    "<span class=\"rating-inbtn\"> 74 </span>\n"
    "<span class=\"rating-inbtn hide-if-zero-113\"> 99 </span>\n"
    "    </a>\n"
    "</span>")

print(re.findall(regex, test_str))

Выход

['215', '82', '74', '99']

Тест с re.finditer

import re

regex = r"rating-inbtn[^>]+>\s*([^\s<]+)\s*<\/"

test_str = ("<span class=\"vote-actions\">\n"
    "    <a class=\"btn btn-default vote-action-good\">\n"
    "        <span class=\"icon thumb-up black black-hover\">&nbsp;</span>\n"
    "        <span class=\"rating-inbtn\">215</span>\n"
    "    </a>\n"
    "    <a class=\"btn btn-default vote-action-bad\">\n"
    "        <span class=\"icon thumb-down grey black-hover\">&nbsp;</span>\n"
    "        <span class=\"rating-inbtn\">82</span>\n"
    "<span class=\"rating-inbtn\"> 74 </span>\n"
    "<span class=\"rating-inbtn hide-if-zero-113\"> 99 </span>\n"
    "    </a>\n"
    "</span>")

matches = re.finditer(regex, test_str, re.MULTILINE)

for matchNum, match in enumerate(matches, start=1):

    print ("Match {matchNum} was found at {start}-{end}: {match}".format(matchNum = matchNum, start = match.start(), end = match.end(), match = match.group()))

    for groupNum in range(0, len(match.groups())):
        groupNum = groupNum + 1

        print ("Group {groupNum} found at {start}-{end}: {group}".format(groupNum = groupNum, start = match.start(groupNum), end = match.end(groupNum), group = match.group(groupNum)))
...