Как найти все строки по bs4?

Я хочу проанализировать определенную страницу с некоторыми изображениями, но изображения не находятся в фиксированном теге a, вот несколько примеров:

<meta name="description" content="This is Text."><meta name="Keywords" content="Weather"><meta property="og:type" content="article"><meta property="og:title" content="Cloud"><meta property="og:description" content="Testing"><meta property="og:url" content="https://weathernews.jp/s/topics/201807/300285/"><meta property="og:image" content="https://smtgvs.weathernews.jp/s/topics/img/201807/201807300285_sns_img_A.jpg?1532940869"><meta name="twitter:title" content="【天地始粛】音や景色から感じる秋の気配"><meta name="twitter:description" content="28日からは「天地始粛(てんちはじめてさむし)」。 「粛」にはおさまる、弱まる等の意味があり、夏の暑さもようやく落ち着いてくる頃とされています。"><meta name="twitter:image" content="https://smtgvs.weathernews.jp/s/topics/img/201807/201807300285_sns_img_A.jpg?1532940869"><link rel="canonical" href="https://weathernews.jp/s/topics/201807/300285/"><link rel="amphtml" href="https://weathernews.jp/s/topics/201807/300285/amp.html"><script async="async" src="https://www.googletagservices.com/tag/js/gpt.js"></script>
<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">

Я попытался использовать приведенный ниже код, чтобы получить все изображения, но безрезультатно. Что мне делать?

soup.find_all(string=re.compile(r"(https://smtgvs.weathernews.jp/s/topics/img/[0-9]+/.+)\?[0-9]+"))

person mikezang    schedule 28.08.2018    source источник
comment
Тема этого сообщения и его содержание противоречат друг другу. Что именно вы просите?   -  person Joseph Seung Jae Dollar    schedule 28.08.2018
comment
Какие URL-адреса следует сопоставить в этом примере? Все четыре?   -  person Peter Gibson    schedule 28.08.2018


Ответы (1)


Я лично считаю, что это один из тех редких случаев, когда применение регулярного выражения ко всему документу без использования анализатора 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
comment
Возможно, с оговоркой, что он также будет соответствовать контенту в комментариях и т. Д. - person Peter Gibson; 28.08.2018
comment
Спасибо за более подробный ответ. но я не очень хорошо разбираюсь в этой теме, можете ли вы отсюда разобрать все изображения url = 'https://weathernews.jp/s/topics/201807/300285/?fm=onebox' resp = requests.get(url) soup = BeautifulSoup(resp.text, 'lxml') - person mikezang; 28.08.2018
comment
@mikezang основная основная идея ответа заключается в том, что вам не нужно использовать beautifulsoup для этой задачи - просто выполните поиск по регулярному выражению внутри resp.text. - person alecxe; 28.08.2018
comment
@alecxe, вы можете помочь мне разобрать https://weathernews.jp/s/topics/201807/300285/?fm=onebox? - person mikezang; 28.08.2018
comment
У меня есть один https://smtgvs.weathernews.jp/s/topics/img/201807/201807300285_sns_img_A.jpg?1532940869"><meta name="twitter:title" content="【天地始粛】音や景色から感じる秋の気配"><meta name="twitter:description content="28日からは「天地始粛(てんちはじめてさむし)」。 「粛」にはおさまる、弱まる等の意味があり、夏の暑さもようやく落ち着いてくる頃とされています。"><meta name="twitter:image" content="https://smtgs.weathernews.jp/s/topics/img/201807/201807300285_sns_img_A.jpg?1532940869, как я могу получить только https://smtgvs.weathernews.jp/s/topics/img/201807/201807300285_sns_img_A.jpg? - person mikezang; 28.08.2018