【问题标题】:Python Re.Search: How to find a substring between two strings, that must also contain a specific substringPython Re.Search:如何在两个字符串之间查找子字符串,该子字符串还必须包含特定的子字符串
【发布时间】:2020-09-22 20:23:55
【问题描述】:

我正在编写一个小脚本来从一个基本的 HTML 页面获取我的 F@H 用户数据。

我想在该页面上找到我的用户名及其前后的数字。

我想要的所有数据都在两个 HTML <tr></tr> 标记之间。

我目前正在使用这个:

re.search(r'<tr>(.*?)</tr>', htmlstring)

我知道这适用于任何子字符串,因为我的问题的所有谷歌结果都显示。这里的区别是我只在该子字符串还包含特定单词时才需要它

但是,它只返回这两个分隔符之间的第一个字符串,而不是全部。

这种模式在页面上出现了数百次。我怀疑它并没有全部得到它们,因为我没有正确处理所有换行符,但我不确定。

如果它会返回所有这些,我至少可以将它们整理出来,找到一个包含我的用户名的用户名,通过每个 result.group(),但我什至做不到。

多年来,我一直在摆弄不同的正则表达式,但不知道我需要哪一个,这让我很沮丧。

TL;DR - 我需要一个re.search() 模式,它可以在两个单词之间找到一个子字符串,它还包含一个特定的单词。

【问题讨论】:

  • 这可能不是最好的方法,你能分享网页网址吗?
  • 视情况而定,您可能想要这样做:stackoverflow.com/questions/57578730/…
  • @NonoLondon 感谢您的回复,但是您首先将我链接到的内容是当我在谷歌上搜索我的问题时我得到的结果。我知道如何在两点之间获取任何子字符串,因为我的代码已经这样做了。我还需要将其限制为特定包含特定单词的时间。
  • 好的,第二个例子呢?可以分享一下网页让我想想吗?

标签: python html regex


【解决方案1】:

有几种方法可以做到,但我更喜欢 pandas 方式:


from urllib import request

import pandas as pd # you need to install pandas

base_url = 'https://apps.foldingathome.org/teamstats/team3446.html'

web_request = request.urlopen(url=base_url).read()

web_df: pd.DataFrame = pd.read_html(web_request, attrs={'class': 'members'})
web_df = web_df[0].set_index(keys=['Name'])
# print(web_df)

user_name_to_find_in_table = 'SteveMoody'
user_name_df = web_df.loc[user_name_to_find_in_table]
print(user_name_df)

那么有很多方法可以做到这一点。只使用 Beautifulsoup 的 find 或 css 选择器,或者像 Peter 建议的那样使用 re?

使用beautifulsoup 和“find”方法,以及re,您可以通过以下方式进行:

import re
from bs4 import BeautifulSoup as bs # you need to install beautifullsoup
from urllib import request




base_url = 'https://apps.foldingathome.org/teamstats/team3446.html'

web_request = request.urlopen(url=base_url).read()

page_soup = bs(web_request, 'lxml') # need to install lxml and bs4(beautifulsoup for Python 3+)

user_name_to_find_in_table = 'SteveMoody'

row_tag = page_soup.find(
    lambda t: t.name == "td"
              and re.findall(user_name_to_find_in_table, t.text, flags=re.I)
).find_parent(name="tr")

print(row_tag.get_text().strip('tr'))

使用 Beautifulsoup 和 CSS 选择器(不是重新,而是 Beautifulsoup):

from bs4 import BeautifulSoup as bs # you need to install beautifulsoup
from urllib import request


base_url = 'https://apps.foldingathome.org/teamstats/team3446.html'

web_request = request.urlopen(url=base_url).read()

page_soup = bs(web_request, 'lxml') # need to install lxml and bs4(beautifulsoup for Python 3+)

user_name_to_find_in_table = 'SteveMoody'

row_tag = page_soup.select_one(f'tr:has(> td:contains({user_name_to_find_in_table})) ')

print(row_tag.get_text().strip('tr'))

在您的情况下,我更喜欢 pandas 示例,因为您可以保留标题并且可以轻松获取其他统计信息,并且运行速度非常快。

使用回复:

所以,最好的输入是 Peters 的评论Link,所以我只是将它改编为 Python 代码(很高兴得到编辑),因为这个解决方案不需要安装任何额外的库。

import re
from urllib import request




base_url = 'https://apps.foldingathome.org/teamstats/team3446.html'

web_request = request.urlopen(url=base_url).read()
user_name_to_find_in_table = 'SteveMoody'
re_patern = rf'<tr>(?:(?:(?:(?!<\/tr>).)*?)\{user_name_to_find_in_table}\b(?:.*?))<\/tr>'
res = re.search(pattern=re_patern, string= str(web_request))

print(res.group(0))


帮助 lin 在正则表达式中使用变量:stackflow

【讨论】:

    【解决方案2】:

    如果我理解正确,这样的事情可能会起作用
    &lt;tr&gt;(?:(?:(?:(?!&lt;\/tr&gt;).)*?)\bWORD\b(?:.*?))&lt;\/tr&gt;

    • &lt;tr&gt;找到“”
    • (?:(?:(?!&lt;\/tr&gt;).)*?) 尽可能少地查找除“
    • ”之外的任何内容
    • \bWORD\b找WORD
    • (?:.*?)) 尽可能少地找到任何东西
    • &lt;\/tr&gt;查找“”

    Sample

    【讨论】:

      猜你喜欢
      • 2014-12-07
      • 1970-01-01
      • 1970-01-01
      • 2016-01-18
      • 2011-03-23
      • 2020-05-28
      • 2013-09-13
      相关资源
      最近更新 更多