使用正则表达式从 HTML 中提取所有值

Posted

技术标签:

【中文标题】使用正则表达式从 HTML 中提取所有值【英文标题】:Use regex to extract all values from HTML 【发布时间】:2019-06-05 23:41:01 【问题描述】:

我需要轻推才能完成这个脚本。

我正在为特定子字符串抓取新闻通讯网站。目的是解析页面中名为 Companies提到.. 的特定部分,并将每个公司的名称转换为 List 数据类型

这是我目前所拥有的,它有效,但只获得第一项:

from bs4 import BeautifulSoup as bs4
import requests
import re

url = 'http://news.hipsternomics.com/issues/how-much-is-your-personal-data-worth-on-the-black-market-148489'
r = requests.get(url).text
soup = bs4(r, 'html.parser')
companies = []
for elem in soup(text=re.compile(r'^(.*?Companies mentioned\b)')):
    companies.append(elem)    

期望的结果:

我想将提到的公司加入到这样的列表中: [Google, Apple, Tesla, Nike, TJX, Ross, L Brands, Dominoes]

我还可以改进正则表达式函数以捕获异常,例如“本期提到的公司:”或“提到的公司:”,如 here 所示。 谢谢。

【问题讨论】:

通常使用正则表达式来解析 HTML 是一个非常糟糕的主意。您应该依赖功能齐全的 XML/HTML 解析器。 【参考方案1】:

您可以通过提供div 类值来访问内容:

import requests, re
from bs4 import BeautifulSoup as soup
d = soup(requests.get('http://news.hipsternomics.com/issues/how-much-is-your-personal-data-worth-on-the-black-market-148489').text, 'html.parser')
new_d = [i for i in d.find_all('div', 'class':'revue-p') if 'Companies mentioned' in i.text][0]
*final_results, _ = [re.sub('^[\w\s]+[,\s:]+|^[,\s]+|\s+$', '', i) for i in new_d.contents if isinstance(i, str)]

输出:

['Google', 'Apple', 'Tesla', 'Nike', 'TJX', 'Ross', 'L Brands', 'Domino’s']

【讨论】:

最后一行左边的语法是什么意思?看起来像是拆包。 @QHarr 是的,它正在拆包。 _ 被称为 throwaway 变量。 @QHarr 很高兴为您提供帮助! 超级有帮助。谢谢。您是否使用工具来构建正则表达式函数?【参考方案2】:

您想要实现的目标无法仅使用正则表达式来完成。一个捕获组只能捕获一件事,并且您无法动态捕获组。 This article has further explanation。

我要做的是首先获取所有公司的字符串

all_companies = re.search(r'Companies mentioned YTD:\s(.*)', orig_text).group(1)
print(all_companies, '\n')

接下来,用,分割字符串

companies_percent = all_companies.split(', ')

# print(companies_percent, '\n')
# Output
# ['Google -1%', 'Apple 0%', 'Tesla +15%', 'Nike +17%', 'TJX +18%', 'Ross -2%', 'L Brands -47%', 'Domino’s +37%'] 

最后去掉公司名称后面的百分比

companies = list(map(lambda x: re.search(r'(.*)\s[\+|-]?\d+%', x).group(1), companies_percent))

# print(companies, '\n')
# Output
# ['Google', 'Apple', 'Tesla', 'Nike', 'TJX', 'Ross', 'L Brands', 'Domino’s'] 

把它们放在一起:

import re
from bs4 import BeautifulSoup as bs4
import requests

url = 'http://news.hipsternomics.com/issues/how-much-is-your-personal-data-worth-on-the-black-market-148489'
r = requests.get(url).text
soup = bs4(r, 'html.parser')

all_companies = re.search(r'Companies mentioned YTD:\s(.*)', soup.get_text()).group(1)
companies_percent = all_companies.split(', ')
companies = list(map(lambda x: re.search(r'(.*)\s[\+|-]?\d+%', x).group(1), companies_percent))

https://repl.it/@hanxue/capturingrepeatedtextgrouppython 的可运行示例

【讨论】:

以上是关于使用正则表达式从 HTML 中提取所有值的主要内容,如果未能解决你的问题,请参考以下文章

如何使用正则表达式从熊猫数据框中的一行中的字符串中提取所有特定值?

使用 PHP 正则表达式从 html 中提取 JSON 对象

是否可以在python中绘制正则表达式来提取所有字符串的属性值

如何在 Python 中使用正则表达式从同一个字符串中提取多个值?

如何使用正则表达式和外壳从字符串中提取值?

从 HTML 中提取文本的正则表达式