Beautifulsoup: ссылка на предыдущую строку в итерации

#python #beautifulsoup

#python #beautifulsoup

Вопрос:

В последние дни я работал над веб-поиском по этой сети: https://www.resultados-futbol.com/primera_division_femenina2020/grupo1/jornada6 Я получаю здесь потрясающую помощь, и я очень близок к достижению своей цели.

Я хочу получить различные элементы сети для создания фрейма данных. Чтобы извлечь эти элементы, я создал цикл, но это приводит к увеличению таблицы и требует некоторых результатов. Проблема в том, что в тех случаях, когда результат равен 0-0, я хотел бы добавить в свой словарь значение «no gol» в «первый гол» и в «минута гола». Текст 0-0 находится в другом tr, чем информация о «первых целях» и «минутах», а затем я не знаю, как это сделать правильно.

Я выполнил этот цикл, создав переменную ‘details’, где содержится информация о ‘первом голе’ и ‘минуте’ первого события каждого матча (это единственное, что мне нужно). Проблема в том, что цикл считывает только первое событие первой игры, и я получаю информацию о целях и минутах только повторно.

Это код:

 from selenium import webdriver
from bs4 import BeautifulSoup
import pandas as pd

driver = webdriver.Chrome(executable_path=r'C:Program FilesChromeDriverchromedriver.exe')
url = 'https://www.resultados-futbol.com/primera_division_femenina2020/grupo1/jornada6'
driver.get(url)

soup = BeautifulSoup(driver.page_source, 'html.parser')

data = []

for row in soup.select('tr.vevent .rstd'):
    teams = row.select_one('.summary').get_text().split(' - ')
    score = row.select_one('.clase').get_text()
    details = soup.select_one('tr.vevent   tr.league-match-events')
    minute = details.select_one('.lme-minute').get_text()
    gol = details.select_one('.url').get_text()
    primergol.append(gol if score != "0-0" else "No gol")
    
    data.append({
        'team1': teams[0],
        'team2':teams[1],
        'score': score,
        'first goal': gol if score != "0-0" else "No gol",
        'first minute': minute if score != "0-0" else "No min"
    })
 

И это результат в «данных». Как вы можете видеть, во всех играх информация о первом голе и минуте взята из первой игры, а не из соответствующей… но в совпадении 0-0, где правильно:

 [{'team1': 'Athletic Fem',
  'team2': 'Real Betis Fem',
  'score': '2-1',
  'first goal': '1-0',
  'first minute': "3'"},
 {'team1': 'Sporting Huelva Fem',
  'team2': 'Deportivo Abanca Fem',
  'score': '0-1',
  'first goal': '1-0',
  'first minute': "3'"},
 {'team1': 'UDG Tenerife Fem',
  'team2': 'Real Sociedad Fem',
  'score': '0-0',
  'first goal': 'No gol',
  'first minute': 'No min'},
 {'team1': 'Atlético Fem',
  'team2': 'Madrid CFF Fem',
  'score': '1-0',
  'first goal': '1-0',
  'first minute': "3'"},
 {'team1': 'Real Madrid Fem',
  'team2': 'Levante Fem',
  'score': '0-3',
  'first goal': '1-0',
  'first minute': "3'"},
 {'team1': 'Sevilla FC Fem',
  'team2': 'Espanyol Fem',
  'score': '4-0',
  'first goal': '1-0',
  'first minute': "3'"},
 {'team1': 'Rayo Vallecano Fem',
  'team2': 'Valencia Fem',
  'score': '3-2',
  'first goal': '1-0',
  'first minute': "3'"},
 {'team1': 'Barcelona Fem',
  'team2': 'Logroño Fem',
  'score': '5-0',
  'first goal': '1-0',
  'first minute': "3'"}]
 

Я что-то упускаю из виду, включая первую строку события в каждое совпадение для сбора данных, но я не знаю, что именно. Любая помощь здесь? Заранее спасибо!

Ответ №1:

Существуют различные решения, которые вы можете использовать для решения этой проблемы.

Решение #1

Очень просто, что вы можете использовать row.findNext('tr') для получения следующего <tr>

Пример

 from selenium import webdriver
from bs4 import BeautifulSoup
import pandas as pd

driver = webdriver.Chrome(executable_path=r'C:Program FilesChromeDriverchromedriver.exe')
url = 'https://www.resultados-futbol.com/primera_division_femenina2020/grupo1/jornada6'
driver.get(url)

soup = BeautifulSoup(driver.page_source, 'html.parser')

data = []

for i, row in enumerate(soup.select('tr.vevent .rstd')):
    teams = row.select_one('.summary').get_text().split(' - ')
    score = row.select_one('.clase').get_text()
    details = row.findNext('tr')
    minute = details.select_one('.lme-minute').get_text()
    gol = details.select_one('.url').get_text() if score != "0-0" else "No gol"

    data.append({
        'team1': teams[0],
        'team2':teams[1],
        'score': score,
        'first goal': gol if score != "0-0" else "No gol",
        'first minute': minute if score != "0-0" else "No min"
    })

data
 

Решение #2

Используйте data-match атрибут в качестве ссылки, чтобы получить следующий <tr>

 match = row.select_one('[data-match]')['data-match']
details = soup.select_one('tr[data-match="' match '"]')
 

Пример

 from selenium import webdriver
from bs4 import BeautifulSoup
import pandas as pd

driver = webdriver.Chrome(executable_path=r'C:Program FilesChromeDriverchromedriver.exe')
url = 'https://www.resultados-futbol.com/primera_division_femenina2020/grupo1/jornada6'
driver.get(url)

soup = BeautifulSoup(driver.page_source, 'html.parser')

data = []

for row in soup.select('tr.vevent'):
    match = row.select_one('[data-match]')['data-match']
    teams = row.select_one('.rstd .summary').get_text().split(' - ')
    score = row.select_one('.rstd .clase').get_text()
    details = soup.select_one('tr[data-match="' match '"]')
    minute = details.select_one('.lme-minute').get_text()
    gol = details.select_one('.url').get_text() if score != "0-0" else "No gol"

    data.append({
        'team1': teams[0],
        'team2':teams[1],
        'score': score,
        'first goal': gol if score != "0-0" else "No gol",
        'first minute': minute if score != "0-0" else "No min"
    })

data
 

Комментарии:

1. Оба они работают идеально. Еще раз спасибо! Я не знал ни одного из решений, поэтому очень интересно продолжать учиться 🙂