【问题标题】:Combining regex with html tags将正则表达式与 html 标签相结合
【发布时间】:2019-03-25 11:38:01
【问题描述】:

我有以下来自 html 页面的文本:

page = 
"""
<font style="DISPLAY: inline; FONT-FAMILY: Times New Roman; FONT-SIZE: 10pt; FONT-WEIGHT: bold">Item 1. Business/</font> Unless otherwise indicated by the context, we use the terms “GE” and “GECC” on the basis of consolidation described in Note 1 to the consolidated financial statements in Part II, Item 8. “Financial Statements and Supplementary Data” of this Form 10-K Report. Also, unless otherwise indicated by the context, “General Electric” means the parent company, General Electric Company (the Company).

General Electric’s address is 1 River Road, Schenectady, NY 12345-6999; we also maintain executive offices at 3135 Easton Turnpike, Fairfield, CT 06828-0001.

<font style="DISPLAY: inline; FONT-FAMILY: Times New Roman; FONT-SIZE: 10pt; FONT-WEIGHT: bold">Item 1A. Risk Factors</font>"""

我想查找获取第 1 项业务和第 1A 项风险因素之间的文本。我不能使用 beautifulsoup,因为每个页面都有不同的 html 标签结构。我使用以下代码来获取文本,但它不起作用:

regexs = ('bold;\">\s*Item 1\.(.+?)bold;\">\s*Item 1A\.',   #<===pattern 1: with an attribute bold before the item subtitle
              'b>\s*Item 1\.(.+?)b>\s*Item 1A\.',               #<===pattern 2: with a tag <b> before the item subtitle
              'Item 1\.\s*<\/b>(.+?)Item 1A\.\s*<\/b>',         #<===pattern 3: with a tag <\b> after the item subtitle          
              'Item 1\.\s*Business\.\s*<\/b(.+?)Item 1A\.\s*Risk Factors\.\s*<\/b') #<===pattern 4: with a tag <\b> after the item+description subtitle 

for regex in regexs:
    match = re.search(regex, page, flags=re.IGNORECASE|re.DOTALL)  #<===search for the pattern in HTML using re.search from the re package. Ignore cases.
    if match:
        soup = BeautifulSoup(match.group(1), "html.parser") #<=== match.group(1) returns the texts inside the parentheses (.*?) 

            #soup.text removes the html tags and only keep the texts
            #rawText = soup.text.encode('utf8') #<=== you have to change the encoding the unicodes
        rawText = soup.text
        print(rawText)
        break

预期的输出是:

Unless otherwise indicated by the context, we use the terms “GE” and “GECC” on the basis of consolidation described in Note 1 to the consolidated financial statements in Part II, Item 8. “Financial Statements and Supplementary Data” of this Form 10-K Report. Also, unless otherwise indicated by the context, “General Electric” means the parent company, General Electric Company (the Company).

General Electric’s address is 1 River Road, Schenectady, NY 12345-6999; we also maintain executive offices at 3135 Easton Turnpike, Fairfield, CT 06828-0001.

我认为,第一个正则表达式应该匹配模式,但它不匹配

编辑:这是实际的 htm 页面和检索文本的方法:

# Import the libraries
import requests
from bs4 import BeautifulSoup
import re
url = "https://www.sec.gov/Archives/edgar/data/40545/000004054513000036/geform10k2012.htm"
HEADERS = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"}
response = requests.get(url, headers=HEADERS)
print(response.status_code)

page = response.text
#Pre-processing the html content by removing extra white space and combining then into one line.
page = page.strip()  #<=== remove white space at the beginning and end
page = page.replace('\n', ' ') #<===replace the \n (new line) character with space
page = page.replace('\r', '') #<===replace the \r (carriage returns -if you're on windows) with space
page = page.replace('&nbsp;', ' ') #<===replace "&nbsp;" (a special character for space in HTML) with space. 
page = page.replace('&#160;', ' ') #<===replace "&#160;" (a special character for space in HTML) with space.
page = page.replace(u'\xa0', ' ') #<===replace "&#160;" (a special character for space in HTML) with space.
page = page.replace(u'/s/', ' ') #<===replace "&#160;" (a special character for space in HTML) with space.
while '  ' in page:
    page = page.replace('  ', ' ') #<===remove extra space

【问题讨论】:

  • 你的预期输出是什么?
  • 请看编辑
  • 输出是否总是在Item 1 BusinessItem 1A Risk factors之间?
  • 是的,几乎总是这样,但是,如果我不使用标签,我可能会得到错误的匹配,因为有时会在文本中使用“项目 1 业务”和“项目 1A 风险因素”跨度>
  • 我们已经忘记了吗? stackoverflow.com/a/1732454/1428679

标签: python html regex


【解决方案1】:

如果你改变你的正则表达式会怎样:

regexs = ('Item 1\.\s*Business\/(.*)',
          'Item 1\.\s*Business\.\s*<\/b(.+?)Item 1A\.\s*Risk Factors\.\s*<\/b')

有效吗?

【讨论】:

    【解决方案2】:

    类似如下?

    import re
    page =  """
    <font style="DISPLAY: inline; FONT-FAMILY: Times New Roman; FONT-SIZE: 10pt; FONT-WEIGHT: bold">Item 1. Business/</font> Unless otherwise indicated by the context, we use the terms “GE” and “GECC” on the basis of consolidation described in Note 1 to the consolidated financial statements in Part II, Item 8. “Financial Statements and Supplementary Data” of this Form 10-K Report. Also, unless otherwise indicated by the context, “General Electric” means the parent company, General Electric Company (the Company).
    
    General Electric’s address is 1 River Road, Schenectady, NY 12345-6999; we also maintain executive offices at 3135 Easton Turnpike, Fairfield, CT 06828-0001.
    
    <font style="DISPLAY: inline; FONT-FAMILY: Times New Roman; FONT-SIZE: 10pt; FONT-WEIGHT: bold">Item 1A. Risk Factors</font>"""
    
    data = re.search('Item 1\. Business\/<\/font> (.*)(<font(.*)">Item 1A. Risk Factors)', page, flags=re.DOTALL).group(1)
    print(data)
    

    【讨论】:

    • 有时不同的标题中间用粗体书写,这就是为什么我还需要指定Item 1A风险因素
    • 如果我分享完整的代码和页面可能会更好
    【解决方案3】:

    我会首先通过贪婪地隔离所有类型的序列来“解析”HTML

    <font[^>]*>([^<>]*)</font>([^<>]+)
    

    这会给我类似的东西,

    ( 'Item 1. Business/', 'Unless otherwise indicated ... CT 06828-0001.' ),
    ( 'Item 1A. Risk Factors', '...')
    

    并处理您的评论“有时在文本中使用“第 1 项业务”和“第 1A 项风险因素””所指出的问题。在这里,文本只能是每个元组的第二个元素,你基本上完全忽略了它。

    然后我会检查每个匹配项的第一个元素中的内容以识别“项目 1”。与“第 1A 项。”。捕获周期将在找到第一个关键字后立即开始,跳过关键字本身,并在找到第二个关键字时停止。

    【讨论】:

    • 也许分享实际页面和完整代码会更好
    【解决方案4】:

    Sooo,我在正则表达式中尝试了NOT TO USE "&lt;font&gt;",因为您说它可能会有所不同,所以我希望这可行。但是,在您的场景中,有很多方法可以破坏正则表达式,因为在许多情况下,肯定是在您的情况下,不应该真正使用正则表达式解析 XML

    >>> import re
    
    
    
    >>> string  = '''
    <font style="DISPLAY: inline; FONT-FAMILY: Times New Roman; FONT-SIZE: 10pt; FONT-WEIGHT: bold">Item 1. Business/</font> Unless otherwise indicated by the context, we use the terms “GE” and “GECC” on the basis of consolidation described in Note 1 to the consolidated financial statements in Part II, Item 8. “Financial Statements and Supplementary Data” of this Form 10-K Report. Also, unless otherwise indicated by the context, “General Electric” means the parent company, General Electric Company (the Company).
    
    General Electric’s address is 1 River Road, Schenectady, NY 12345-6999; we also maintain executive offices at 3135 Easton Turnpike, Fairfield, CT 06828-0001.
    
    <font style="DISPLAY: inline; FONT-FAMILY: Times New Roman; FONT-SIZE: 10pt; FONT-WEIGHT: bold">Item 1A. Risk Factors</font>'''
    
    
    
    
    >>> result = re.findall('Item[\s]*1.[\s]*Business[/<]*[\S]*?[>]*[\s]+([\S\s]+?)[/<]+[\S\s]*?[>]*?Item 1A. Risk Factors', string)
    
    
    
    
    
    #Output
    >>> print(result[0])
    Unless otherwise indicated by the context, we use the terms “GE” and “GECC” on the basis of consolidation described in Note 1 to the consolidated financial statements in Part II, Item 8. “Financial Statements and Supplementary Data” of this Form 10-K Report. Also, unless otherwise indicated by the context, “General Electric” means the parent company, General Electric Company (the Company).
    
    General Electric’s address is 1 River Road, Schenectady, NY 12345-6999; we also maintain executive offices at 3135 Easton Turnpike, Fairfield, CT 06828-0001.
    

    【讨论】:

    • 我知道 regex 通常不是 html 的最佳解决方案,但是我没有任何其他选择,因为 Edgar 网站中页面的 html 结构发生了变化。
    • 是的,我阅读了您的帖子,这就是我制作正则表达式解决方案的原因。我遇到过几种情况,其中正则表达式是 xml 的唯一选择,并且发现 Python XML 库很糟糕,所以我完全理解。看看我的解决方案是否有效。告诉我。
    • 它适用于示例,但不适用于真实页面本身,在我看来,应该适用于页面,'bold;\">\sItem 1\.(. +?)bold;\">\sItem 1A\.'但它不起作用......
    • 您能否发布其他示例,以便我可以具体了解我要构建的内容?如果没有看到所有原始文本或至少更多示例,很难得到一个想法。
    • 我分享了原始的 htm,如果它适用于这个,那么它也适用于其他人
    【解决方案5】:

    因此,鉴于页面的全文,您很可能会受到伤害。老实说,您对问题的描述非常具有误导性,但是无论如何,这可能就是您要寻找的东西,但它非常庞大

    >>> import re
    >>> import requests
    
    
    >>> page = requests.get("https://www.sec.gov/Archives/edgar/data/40545/000004054513000036/geform10k2012.htm").text
    
    
    
    >>> segment_of_page = re.findall('(?i)align=[\"]*center[\"]*[\S\ ]+?Part[\s]*I(?!I)[\S\s]+?Item[\S\s]*?1(?![\d]+)[\S\s]{1,50}Business[\S\s]{40,}?>Item[\S\s]{1,50}1A\.[\S\s]{1,50}(?=Risk)', page)
    
    
    
    >>> parsed_data_sets = []
    
    
    
    >>> for i in range(len(segment_of_page)):
            if len(segment_of_page[i]) > 35:
                parsed_data = re.findall('(?:<[\S\s]+?>)+([\S\s]+?)(?=<[\S\s]+?>)+', segment_of_page[i])
                for ii in range(len(parsed_data)):
                    parsed_data_sets.append(parsed_data[ii])
    
    
    >>> for i in range(len(parsed_data_sets)):
            if len(parsed_data_sets[i]) > 35:
                print('\n\n\n===============\n\n')
                print(parsed_data_sets[i])
    
    
    
    
    
    #Output
    ===============
    
    
    Unless otherwise indicated by the context, we use the terms &#8220;GE&#8221; and &#8220;GECC&#8221; on the basis of consolidation described in Note 1 to the consolidated financial statements in Part II, Item 8. &#8220;Financial Statements and Supplementary Data&#8221; of this Form 10-K Report. Also, unless otherwise indicated by the context, &#8220;General Electric&#8221; means the parent company, General Electric Company (the Company).
    
    
    ===============
    
    
    General Electric&#8217;s address is 1 River Road, Schenectady, NY 12345-6999; we also maintain executive offices at 3135 Easton Turnpike, Fairfield, CT 06828-0001.
    
    
    ===============
    
    
    We are one of the largest and most diversified infrastructure and financial services corporations in the world. With products and services ranging from aircraft engines, power generation, oil and gas production equipment, and household appliances to medical imaging, business and consumer financing and industrial products, we serve customers in more than 100 countries and employ approximately 305,000 people worldwide. Since our incorporation in 1892, we have developed or acquired new technologies and services that have broadened and changed considerably the scope of our activities.
    
    
    ===============
    

    自您上次提取字符串后,部分文档发生了变化,但如果可行,请告诉我。

    【讨论】:

    • 我想我们快到了,从链接中,我需要第 1 项下的所有内容
    • 好的。我做了一个编辑。顺便说一句,你为通用电气工作?还是只是与他们签订合同?
    • 不,我正在攻读博士学位,只需要用于研究目的的数据。它适用于这个特定问题,但也许我的问题更广泛,因此没有解决方案......我想如果我在正则表达式中使用某种“粗体”html标签,我可以找到一个更通用的解决方案,显然,事实并非如此
    • 不,使用“粗体”、“字体”和任何标签都不会影响这一点。但实际上,很难理解你想要什么,因为这是可能的。我在上面发布的解决方案捕获了段落文本between Item 1 and Item 2。你真的想要Item 1 Business and Item 1A Risk factors 之间的数据吗,因为我上面的内容就是这样做的,而且只需一个很小的改变就可以让它捕获Item 1 Business and Item 1A Risk factors 之间的所有内容
    • 我更新了。以上应该只返回Item 1 Business and Item 1A Risk factors 之间的解析数据
    猜你喜欢
    • 1970-01-01
    • 2014-02-25
    • 2011-01-24
    • 2021-09-30
    • 1970-01-01
    • 2014-08-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多