如何从HTML中提取特定数据?

How to extract specific data from HTML?

提问人:Marco Almeida 提问时间:3/9/2023 最后编辑:Marco Almeida 更新时间:3/9/2023 访问量:64

问:

我需要从 HTML 中提取以下数据:日期、时间、第一个 Jogo,如果复选标记符号出现在第一次、第二次、第三次或第四次,则显示 0,如果没有复选标记,则显示 0。

当复选标记存在时,返回的所有数据都很好,但是当没有复选标记时,它只显示日期和时间。

我的python代码是:


from bs4 import BeautifulSoup

html = """
<div class="body">
   <div class="pull_right date details" title="09.03.2023 01:08:10 UTC-03:00">
      01:08
   </div>
   <div class="from_name">
      🤖🥇 𝑬𝒂𝒔𝒚 𝑩𝒐𝒕 - 𝑶𝒗𝒆𝒓 2.5 
   </div>
   <div class="text">
      Easy Bot - Over 2.5<br><br>🏆 Liga: Sul-Americana<br>🚦 Entrada: Over 2.5 FT<br>⚽ Jogos: ✅ 04:10 04:13 04:16 (04:19)<br><br><strong>Link: </strong><a href="https://www.bet365.com/#/AVR/B146/R%5E1/">https://www.bet365.com/#/AVR/B146/R%5E1/</a><br><br>🍀 24h:100% de acerto nas últimas 24h<br><br>✅✅✅✅✅✅ .
   </div>
</div>
"""

# parse the HTML
soup = BeautifulSoup(html, 'html.parser')

d_str = soup.select_one('div.date.details')['title']
calendar = d_str.split(" ")
print("Date: ",calendar[0])
print("Time: ",calendar[1])
for sts in soup.select_one('div.text').stripped_strings:
    if "⚽ Jogos: " in sts:
        jugos = (sts.split('⚽ Jogos: ')[1].split(" "))
        ind = jugos.index('✅')+1
        jugos.remove("✅")
        print("Jogo 1: ", jugos[0])
        print("Checkmarked: ", ind)

请注意,复选标记“属于”时间。所以它可以是第一次、第二次、第三次或第四次 Jogos 时间。

但有时不会有复选标记。发生这种情况时,输出应为:

日期: XXX 时间:XXX 乔戈 1:XXX 选中:0

那么,这段代码有什么问题呢?

python-3.x beautifulsoup html 解析

评论

1赞 Jack Fleeting 3/9/2023
有些不清楚的地方:你说“如果复选标记符号出现在第一次、第二次、第三次或第四次”——在你的 html 中,你有一行 Jogos 以一个复选标记和 4 次开头(括号中一个);这是否意味着复选标记“属于”第一次?我建议您编辑您的示例以添加另一个具有不同复选标记排列的示例,重要的是,新示例的确切预期输出。
1赞 Marco Almeida 3/9/2023
是的,复选标记“附加”到标记它的时间上。我将用更多细节和预期输出来编辑问题。

答:

0赞 HedgeHog 3/9/2023 #1

不确定预期结果应该是什么样子,或者有多少项需要迭代,因此此代码应指向一个方向。


这里的问题是需要完全匹配。string='⚽ Jogos:'

from bs4 import BeautifulSoup

html = '''
<div class="body">
   <div class="pull_right date details" title="09.03.2023 01:08:10 UTC-03:00">
      01:08
   </div>
   <div class="from_name">
      🤖🥇 𝑬𝒂𝒔𝒚 𝑩𝒐𝒕 - 𝑶𝒗𝒆𝒓 2.5 
   </div>
   <div class="text">
      Easy Bot - Over 2.5<br><br>🏆 Liga: Sul-Americana<br>🚦 Entrada: Over 2.5 FT<br>⚽ Jogos: ✅ 04:10 04:13 04:16 (04:19)<br><br><strong>Link: </strong><a href="https://www.bet365.com/#/AVR/B146/R%5E1/">https://www.bet365.com/#/AVR/B146/R%5E1/</a><br><br>🍀 24h:100% de acerto nas últimas 24h<br><br>✅✅✅✅✅✅ .
   </div>
</div>
'''
soup = BeautifulSoup(html)

data = []

for e in soup.select('.text'):    
    for s in e.stripped_strings:
        if 'Jogos' in s:
            s=s.split()[2:]
            jogo_times = [t for t in s if '✅' not in t]
            jogo_check = [s[i+1] for i,t in enumerate(s) if '✅' in t]
            d = {
                'date':e.find_previous('div',{'class':'date'}).get('title')[:10],
                'time':e.find_previous('div',{'class':'date'}).get_text(strip=True),
                'jogo_times':jogo_times,
                'jogo_time_checked':jogo_check
            }
            break
    if d:
        data.append(d)
        d = None   
    else:
        print('no jogo')
data

输出

[{'date': '09.03.2023',
  'time': '01:08',
  'jogo_times': ['04:10', '04:13', '04:16', '(04:19)'],
  'jogo_time_checked': ['04:10']}]

评论

0赞 Marco Almeida 3/9/2023
我没有从您的代码中得到任何输出。
0赞 HedgeHog 3/9/2023
如果您完全像这样使用示例,则应直接从您的环境中打印数据,否则必须将其打印出来。如果您已经调整了代码,则需要更多详细信息
1赞 Jack Fleeting 3/9/2023 #2

我会这样做:

d_str = soup.select_one('div.date.details')['title']
calendar = d_str.split(" ")
print("Date: ",calendar[0])
print("Time: ",calendar[1])
for sts in soup.select_one('div.text').stripped_strings:
    if "⚽ Jogos: " in sts:
        jugos = (sts.split('⚽ Jogos: ')[1].split(" "))
        if "✅" in jugos:
           ind = jugos.index('✅')+1
           print("Checkmarked: ", ind)
           jugos.remove("✅")
           print(jugos)
    else:
        print(jugos)
        print("Checkmarked: NA")

带复选标记的输出:

Date:  09.03.2023
Time:  01:08:10
['04:10', '04:13', '04:16', '(04:19)']
Checkmarked:  1

不带复选标记的输出:

Date:  09.03.2023
Time:  01:08:10
['04:10', '04:13', '04:16', '(04:19)']
Checkmarked: NA

当然,您可以将输出添加到列表中,而不是打印,等等。

评论

0赞 Marco Almeida 3/9/2023
代码很好,但是当它面对没有复选标记的 Jogos 时,它只显示日期和时间,而不显示 Jogos 时间。我将更新问题以添加它。
0赞 Jack Fleeting 3/9/2023
@MarcoAlmeida 我没有得到与您相同的结果,但我编辑了问题以考虑没有复选标记。