如何抓取与其对应日期匹配的数据



我正试图在一个网站上搜索板球俱乐部的成绩,但某一日期的比赛次数并没有固定。例如:2022年9月17日星期六有1场比赛,2022年9月下星期六有3场比赛。如果网站将日期分为不同的类别或表格,这会很简单,但事实并非如此。

import requests
import urllib3
import pandas as pd
from html.parser import HTMLParser
from bs4 import BeautifulSoup

网站的URL如下所示:-

#Url = Page 1 of results
url = 'https://halstead.play-cricket.com/Matches?fixture_month=13&home_or_away=both&page=1&q%5Bcategory_id%5D=all&q%5Bgender_id%5D=all&search_in=&season_id=255&seasonchange=f&selected_season_id=255&tab=Result&team_id=&utf8=%E2%9C%93&view_by=year'
data = requests.get(url).text
soup = BeautifulSoup(data, 'lxml')

主代码

#Creating the table
main_lists = {'Team A':[], '':[],'Team B':[]}
entries = soup.findAll('p', class_='txt1')
list = []
for entries in entries:
#Everything in one list
list.append(entries.text.strip('/n'))
#Separating entries by odd and even index
l = range(len(list))
list_even = list[::2]
list_odd = list [1::2]
for list_even in list_even:
main_lists['Team A'] += [list_even]
main_lists[''] += ['vs']
for list_odd in list_odd:
main_lists['Team B'] += [list_odd]
#Turn lists into dataframe
df_main = pd.DataFrame(main_lists)
#Getting result
res_list = []
x = 0
while x < df_main.shape[0]:
res = soup.select('.fonts-gt')[x];x += 1
res_list.append(res.text)
res_list = [sub.replace('  ',' ') for sub in res_list]
df_main['Result'] = res_list
df_main = df_main.reindex(columns=['Result', 'Team A', 'Team B'])
#Getting the Date
date = soup.findAll('div', class_='col-sm-12 text-center text-md-left title2 padding_top_for_mobile')
date_table = []
for date in date:
date_table.append(date.text.strip('n'))
date_table2 = [sub.replace('2022n', '2022') for sub in date_table]
df_date = pd.DataFrame(date_table2)
print(f'The length of df_main is {len(df_main)}, and the length of df_date is {len(df_date)}')

在这里,我们可以看到两个数据帧的行数的差异。

df_main的长度为25,df_date的长度为12

我确实尝试过使用类似的东西:-

items = soup.find_all(class_=['row ml-large-0 mr-large-0','col-sm-12 d-md-none match-status-mobile'])
for item in items:
print(item.text)

它给出了类似于:但我仍然不知道如何按日期来区分这些。

尝试更改选择策略并一次性提取信息。对匹配项进行迭代,并使用find_previous()提取列出匹配项的相应日期。

在较新的代码中,避免使用旧的语法findAll(),而使用find_all()select()css selectors-要了解更多信息,请花一分钟时间检查文档

示例

import requests
from bs4 import BeautifulSoup
url='https://halstead.play-cricket.com/Matches?fixture_month=13&home_or_away=both&page=1&q%5Bcategory_id%5D=all&q%5Bgender_id%5D=all&search_in=&season_id=255&seasonchange=f&selected_season_id=255&tab=Result&team_id=&utf8=%E2%9C%93&view_by=year'
soup = BeautifulSoup(requests.get(url).text)
data = []
for e in soup.select('table'):
d = dict(zip(['Team A','Team B'],[t.text for t in e.select('.txt1')]))
d.update({
'Result':e.div.text,
'Date':e.find_previous('div',class_='title2').get_text(strip=True)
})
data.append(d)
pd.DataFrame(data)

输出

022年9月17日星期六>取消>
团队A团队B
0埃塞克斯郡哈尔斯特德CC-第一届XIFakenham CC-第一个XIFakenham CC被8次WICKETS击败
1Battisford&CC区-XI第一日星期六Halstead CC,埃塞克斯郡-XI第二日取消2022年9月10日星期六
2Maldon CC-第四届XI埃塞克斯郡哈尔斯特德CC-第三届XI2022年9月10日星期六
3埃塞克斯郡哈尔斯特德CC-第一届XIWorlington CC-第一任XI哈斯特德CC,Essex WON BY 23 RUNS2022年9月10日星期六
21Halstead CC,埃塞克斯郡-NECL第一届XIWickham St Pauls CC-第一届XIWickham St Pauls CC被两个WICKETS击败2022年7月31日星期日
22埃塞克斯郡哈尔斯特德CC-XI第二郡West Bergholt CC-XI第一郡两个郡埃塞克斯郡霍尔斯特德CC 3次跑步2022年7月30日星期六
23Halstead CC,埃塞克斯郡-第三届XI艾伯顿&CC区-第三届XIABBERTON&2022年7月30日星期六,地区CC被6个WICKE
24Coggeshall镇CC-第一届XI埃塞克斯郡哈尔斯特德CC-第一任XIHalstead CC,Essex WON BY 117 RUNS2022年7月30日星期六

这很困难,但是,一旦我改变了获取数据的方法,我就可以获得您想要的结果。

变化是:

  • 获取tableHTML元素内部的数据,该元素具有匹配项(,即团队A、团队B和结果)
  • 对于日期,当所述div没有tableHTML元素时,获取div内部的文本

这是修改后的代码:

import requests
import urllib3
import pandas as pd
from html.parser import HTMLParser
import bs4
from bs4 import BeautifulSoup
#Url = Page 1 of results
url = 'https://halstead.play-cricket.com/Matches?fixture_month=13&home_or_away=both&page=1&q%5Bcategory_id%5D=all&q%5Bgender_id%5D=all&search_in=&season_id=255&seasonchange=f&selected_season_id=255&tab=Result&team_id=&utf8=%E2%9C%93&view_by=year'
data = requests.get(url).text
soup = BeautifulSoup(data, 'lxml')
# Variables: 
result_array = [] # It will contain the list of dictionaries with the desired data.
team_a = "" # Value for "Team A" column.
team_b = "" # Value for "Team B" column.
result = "" # Value for "Result" column. 
temp_date = "" # Stores the date.
# Get the main div that contains the data to extract: 
div_principal = soup.find("div", class_="tab-pane fade active in")
# Loop the divs "i.e. the data of the matches and the date" found in the main container div: 
for indx, div in enumerate(div_principal):
# Loop only the valid elements with the data to get:
if (indx >= 5 and indx <= 77): 
# Check if the element is a valid BeautifulSoup "Tag" element: 
# Source: https://stackoverflow.com/a/42802393/12511801
if type(div) is bs4.element.Tag: 
# If no "table" is found on this div, then, it's a "date" - that's due I'm getting the "data" contained on the "table" HTML element: 
if (div.find("table") is not None):
# Get the values for "Team A", "Team B" and "Result": 
team_a = div.find('table').find("p", class_="txt1").get_text("", strip=True)
team_b = div.find('table').find("td", class_="col-xs-5 col-sm-3 col-md-3 text-center text-md-left card-table-r bgGray").find("p", class_="txt1").get_text("", strip=True)
# Here the original text has double spaces. 
# Example: FAKENHAM CC WON  BY 8 WICKETS 
# (notice the double spaces between the words "WON" and "BY"). 
result = div.find('table').find("div", class_="fonts-gt").get_text("", strip=True).replace("  ", " ") # <== Here 
else: 
# Get the "date" and clear the other variables: 
temp_date = div.get_text("", strip=True)
team_a = ""
team_b = ""
result = ""
# Add elements to the list:
if (len(team_a) > 0):
result_array.append({"Team A" : team_a, "Team B": team_b, "Result": result, "Date": temp_date})
# Remove duplicates - source: https://stackoverflow.com/a/9427216/12511801
result_array = [i for n, i in enumerate(result_array) if i not in result_array[n + 1:]]
# Build and display dataframe:
df_final = pd.DataFrame(result_array)
display(df_final)

结果:

结果日期霍尔斯特德CC,艾塞克斯赢了25次2022年9月3日星期六米斯特里CC-NECL T202022年8月27日星期六>霍尔斯特德CC,艾塞克斯被5个WICKETS击败>[/tr>2022年7月31日星期日
索引团队A团队B
0Halstead CC,埃塞克斯-第一届XI省Fakenham CC-1第一届XI省Fakenham CC被8个WICKETS击败2022年9月17日星期六
1Battisford&CC区-XI第一区哈尔斯特德CC,埃塞克斯-XI第二区取消2022年9月10日星期六
2马尔顿CC-4第三届XI省哈尔斯特德CC,埃塞克斯-第三届XI省取消2022年9月10日星期六
3霍尔斯特德CC,埃塞克斯第一届XI沃灵顿CC-1st XI哈尔斯特德CC
4霍尔斯特德CC,埃塞克斯-第二届XI邓莫CC-2和XI2022年9月3日星期六
5Mistley CC-1st XI哈尔斯特德CC,埃塞克斯-第一XI哈尔斯特德CC,艾塞克斯被4个WICKETS击败
6埃塞克斯郡哈尔斯特德CC,NECL T20Coggeshall镇CC-NECL T202022年8月28日星期日,埃塞克斯郡霍尔斯特德CC以90分之差获胜
7哈尔斯特德CC,埃塞克斯NECL T202022年8月28日星期日,埃塞克斯哈尔斯特德CC以152跑的成绩获胜
8霍尔斯特德CC,埃塞克斯第二届XIStowupland CC-1st XI哈尔斯特德CC
9霍尔斯特德CC,埃塞克斯第三届XI队真实赔率CC-1st XI队哈尔斯特德CC
10凯斯格雷夫CC-1st XI哈尔斯特德CC,埃塞克斯-第一XI哈尔斯特德CC,艾塞克斯被7个WICKETS击败
11Sudbury CC,萨福克郡-星期日XI第一届Halstead CC,埃塞克斯-NECL第一届XISudbury CC,Suffolk以22分的成绩获胜2022年8月21日星期日
12圣玛格丽特CC,萨福克-第一XI省哈尔斯特德CC,埃塞克斯-第二XI省圣玛格丽特CC,苏福尔克以60分的优势获胜2022年8月20日星期六
13Kelvedon和Feering CC-2nd XIHalstead CC,Essex-3rd XIKelvedon和Feerining CC被1个WICKET击败2022年8月20日星期六
14霍尔斯特德CC,埃塞克斯第一届XIWoolpit CC-周六第一届XI哈尔斯特德CC
15霍尔斯特德CC,埃塞克斯-第二届XI省米尔登霍尔CC,萨福克-第四届XI省哈尔斯特德CC
16霍尔斯特德CC,埃塞克斯-第三届XIWitham CC-3第三届XI哈尔斯特德CC
17Wivenhoe镇CC-1st XIHalstead CC,Essex-1st XIHalstead CC,Essex WON BY 3 WICKETS2022年8月13日星期六
18霍尔斯特德CC,埃塞克斯-NECL第一届XI科尔切斯特和东埃塞克斯CC-NECL第一届XI2022年8月7日星期日
19伊普斯维奇CC-1st XI哈尔斯特德CC,埃塞克斯-XI第二届哈尔斯特德CC,艾塞克斯以1次跑的优势获胜2022年8月6日星期六
20霍尔斯特德CC,埃塞克斯-第一XI省海上克拉克顿CC-周六XI省哈尔斯特德CC
21霍尔斯特德CC,埃塞克斯-NECL第一届XI威克姆圣保罗CC-1st XI威克姆圣保罗CC被两个WICKETS击败
22Halstead CC,埃塞克斯-第二XI省West Bergholt CC-两个县,第一XI省Halstead CC2022年7月30日星期六
23Halstead CC,埃塞克斯-第三XI省Abberton&CC-3区XIABBERTON&2022年7月30日星期六,CC区赢得6个奖杯
24科格斯霍尔镇CC-1st XI哈尔斯特德CC,埃塞克斯-第一XI哈尔斯特德CC,艾塞克斯以117次跑的成绩获胜2022年7月30日星期六

相关内容

  • 没有找到相关文章

最新更新