Я лично считаю, что это один из тех редких случаев, когда применение регулярного выражения ко всему документу без использования анализатора HTML - самый простой и хороший способ. И, поскольку вы на самом деле просто ищете URL-адреса и не сопоставляете какие-либо HTML-теги в регулярном выражении, в этой ветке были отмечены вопросы не действительны для этого случая:
In [1]: data = """
...: <meta name="twitter:image" content="https://smtgvs.weathernews.jp/s/topics/img/201807/201807300285_sns_img_A.jpg?1532940869">
...: <img style="width:100%" id="box_img1" alt="box1" src="https://smtgvs.weathernews.jp/s/topics/img/dummy.png" class="lazy" data-original="https:
...: //smtgvs.weathernews.jp/s/topics/img/201807/201807300285_box_img1_A.png?1503665797">`
...: <img style="width:100%" id="box_img2" alt="box2" src="https://smtgvs.weathernews.jp/s/topics/img/201807/201807300285_box_img2_A.jpg?1503378518
...: ">
...: """
In [2]: import re
In [3]: pattern = re.compile(r"https://smtgvs.weathernews.jp/s/topics/img/[0-9]+/.+\?[0-9]+")
In [4]: pattern.findall(data)
Out[4]:
['https://smtgvs.weathernews.jp/s/topics/img/201807/201807300285_sns_img_A.jpg?1532940869',
'https://smtgvs.weathernews.jp/s/topics/img/201807/201807300285_box_img1_A.png?1503665797',
'https://smtgvs.weathernews.jp/s/topics/img/201807/201807300285_box_img2_A.jpg?1503378518']
Если вам интересно, как бы вы применили шаблон регулярного выражения к нескольким атрибутам в BeautifulSoup
, это может быть что-то вроде этих строк (не очень красиво, я знаю):
In [6]: results = soup.find_all(lambda tag: any(pattern.search(attr) for attr in tag.attrs.values()))
In [7]: [next(attr for attr in tag.attrs.values() if pattern.search(attr)) for tag in results]
Out[7]:
[u'https://smtgvs.weathernews.jp/s/topics/img/201807/201807300285_sns_img_A.jpg?1532940869',
u'https://smtgvs.weathernews.jp/s/topics/img/201807/201807300285_box_img1_A.png?1503665797',
u'https://smtgvs.weathernews.jp/s/topics/img/201807/201807300285_box_img2_A.jpg?1503378518']
Здесь мы в основном перебираем все атрибуты всех элементов и проверяем соответствие шаблону. Затем, как только мы получим все совпадающие теги, мы перебираем результаты и получаем значение соответствующего атрибута. Мне действительно не нравится, что мы применяем проверку регулярного выражения дважды - при поиске тегов и при проверке желаемого атрибута совпадающего тега.
lxml.html
и его возможности XPath позволяют работать с атрибутами напрямую, но lxml
поддерживает XPath 1.0, в котором нет регулярного выражения служба поддержки. Вы можете делать что-л. Вроде:
In [10]: from lxml.html import fromstring
In [11]: root = fromstring(data)
In [12]: root.xpath('.//@*[contains(., "smtgvs.weathernews.jp") and contains(., "?")]')
Out[12]:
['https://smtgvs.weathernews.jp/s/topics/img/201807/201807300285_sns_img_A.jpg?1532940869',
'https://smtgvs.weathernews.jp/s/topics/img/201807/201807300285_box_img1_A.png?1503665797',
'https://smtgvs.weathernews.jp/s/topics/img/201807/201807300285_box_img2_A.jpg?1503378518']
что не на 100% то, что вы сделали, и, вероятно, приведет к ложным срабатываниям, но вы можете пойти дальше и при необходимости добавить дополнительные проверки «подстроки в строке».
Или вы можете получить все атрибуты всех элементов и отфильтровать их, используя уже имеющееся регулярное выражение:
In [14]: [attr for attr in root.xpath("//@*") if pattern.search(attr)]
Out[14]:
['https://smtgvs.weathernews.jp/s/topics/img/201807/201807300285_sns_img_A.jpg?1532940869',
'https://smtgvs.weathernews.jp/s/topics/img/201807/201807300285_box_img1_A.png?1503665797',
'https://smtgvs.weathernews.jp/s/topics/img/201807/201807300285_box_img2_A.jpg?1503378518']
person
alecxe
schedule
28.08.2018