如何通过 bs4 查找所有字符串?
How to find all strings by 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]+"))
我个人认为这是在不使用HTML解析器的情况下将正则表达式应用于完整文档是最简单和好的方法的罕见情况之一.而且,由于您实际上只是在寻找 URL,而不匹配正则表达式中的任何 HTML 标记,因此 in this thread 的要点对于这种情况无效:
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%,并且可能会产生误报,但您可以更进一步,并在需要时添加更多 "substring in a string" 检查。
或者,您可以获取所有元素的所有属性并使用已有的正则表达式进行过滤:
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']
我想用一些图片解析特定页面,但是图片不在固定标签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]+"))
我个人认为这是在不使用HTML解析器的情况下将正则表达式应用于完整文档是最简单和好的方法的罕见情况之一.而且,由于您实际上只是在寻找 URL,而不匹配正则表达式中的任何 HTML 标记,因此 in this thread 的要点对于这种情况无效:
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%,并且可能会产生误报,但您可以更进一步,并在需要时添加更多 "substring in a string" 检查。
或者,您可以获取所有元素的所有属性并使用已有的正则表达式进行过滤:
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']