BeautifulSoup, запросы, ошибка сохранения фрейма данных в массивы Excel

Я новичок в Python и помогаю в школьном проекте. Любая помощь горячо приветствуется. БЛАГОДАРЮ. Я получаю сообщение об ошибке, когда он попадает в 2004 и 2003 год. И это вызвано списком result_list. Ошибка "ValueError: все массивы должны быть одинаковой длины". Как я могу ввести код, который исправляет это. Важны баллы....

import requests
import pandas as pd
from pandas import ExcelWriter
from bs4 import BeautifulSoup
#from openpyxl.writer.excel import ExcelWriter
import openpyxl
#from openpyxl import load_workbook
import csv

year_id = ['2019','2018','2017','2016','2015','2014','2013','2012','2011','2010','2009','2008','2007','2006','2005','2004','2003']

i=0
while i <= len(year_id)-1: 
    url = 'https://lehighsports.com/sports/mens-soccer/schedule/' + str(year_id[i])
    lehigh = requests.get(url).text
    soup = BeautifulSoup(lehigh,'lxml')

    date_list = []
    for date in soup.find_all('div',class_="sidearm-schedule-game-opponent-date"):
        date_list.append(date.get_text(strip=True, separator=' '))

    name_list = []
    for name in soup.find_all('div',class_="sidearm-schedule-game-opponent-name"):
        name_list.append(name.get_text(strip=True, separator=' '))

    result_list = []
    for result in soup.find_all('div',class_="sidearm-schedule-game-result"):
        result_list.append(result.get_text(strip=True, separator=' '))

    opp_list = []
    for opp in soup.find_all('div',class_="sidearm-schedule-game-opponent-text"):
        opp_list.append(opp.get_text(strip=True, separator=' '))

    conf_list = []
    for conf in soup.find_all('div',class_="sidearm-schedule-game-conference-conference"):
        conf_list.append(conf.get_text(strip=True))

    dict = {'date':date_list,'opponent':name_list,'result':result_list,'list':opp_list,'conference':conf_list}
    df = pd.DataFrame(dict)

    workbook1 = openpyxl.load_workbook('lehigh.xlsx')
    writer = pd.ExcelWriter('lehigh.xlsx', engine='openpyxl') 
    writer.book = workbook1
    df.to_excel(writer, sheet_name=str(year_id[i]),index=False,startrow=0,startcol=0)
    writer.save()
    writer.close()

    i = i+1

person Herman L    schedule 06.01.2020    source источник


Ответы (2)


Код обновлен:

import requests
from bs4 import BeautifulSoup
import pandas as pd
from itertools import zip_longest

d = []
n = []
res = []
op = []
yr = []
with requests.Session() as req:
    for year in range(2003, 2020):
        print(f"Extracting Year# {year}")
        r = req.get(
            f"https://lehighsports.com/sports/mens-soccer/schedule/{year}")
        if r.status_code == 200:
            soup = BeautifulSoup(r.text, 'html.parser')
            for date in soup.findAll("div", {'class': 'sidearm-schedule-game-opponent-date flex-item-1'}):
                d.append(date.get_text(strip=True, separator=" "))
            for name in soup.findAll("div", {'class': 'sidearm-schedule-game-opponent-name'}):
                n.append(name.get_text(strip=True))
            for result in soup.findAll("div", {'class': 'sidearm-schedule-game-result'}):
                result = result.get_text(strip=True)
                res.append(result)
            if len(d) != len(res):
                res.append("None")
            for opp in soup.findAll("div", {'class': 'sidearm-schedule-game-opponent-text'}):
                op.append(opp.get_text(strip=True, separator=' '))
                yr.append(year)


data = []
for items in zip_longest(yr, d, n, res, op):
    data.append(items)

df = pd.DataFrame(data, columns=['Year', 'Date', 'Name', 'Result', 'Opponent']).to_excel(
    'lehigh.xlsx', index=False)

Выход: регистрация онлайн

person αԋɱҽԃ αмєяιcαη    schedule 06.01.2020
comment
это удивительно и даже быстрее. ты великолепен. Спасибо. это потрясающе. - person Herman L; 07.01.2020
comment
конечно рад. Кроме того, еще один вопрос, как я могу получить год в столбце 1, чтобы я знал, из какого года идет строка счета. Ваш код потрясающий - такой чистый и быстрый. Спасибо - person Herman L; 07.01.2020
comment
Как мне проголосовать? Извините, никогда не делал этого раньше (никого не просили). Кроме того, еще одна услуга - есть ли способ разделить результат игры (текст-курсив-расписание-игры-результата), например. Ж, 2-0 в Ж и 2-0. Не могу понять, как получить каждый из них отдельно при проверке HTML. Спасибо. Пожалуйста, дайте мне знать, как проголосовать за. Был действительно полезен. Вы должны начать взимать $$!! - person Herman L; 08.01.2020
comment
проголосовал .. наконец понял, что это была галочка! Готово. Кроме того, еще одна услуга - есть ли способ разделить результат игры (текст-курсив-расписание-игры-результата), например. Ж, 2-0 в Ж и 2-0. Не могу понять, как получить каждый из них отдельно при проверке HTML - person Herman L; 08.01.2020
comment
эй αԋɱҽԃ αмєяιcαη - ненавижу это говорить, но я на месте проверил счет Джорджтауна, где Лихай проиграл 2-1. В вашем коде он выигрывает со счетом 1: 0. Что-то не так. Код chitown88 работает, но этот человек помещает его в отдельные вкладки - я предпочитаю ваш в одной вкладке. Я не могу понять, что не так с вашим кодом, так как оценки неверны. жаль сообщать вам. танки - person Herman L; 09.01.2020
comment
Я вижу, что за последние несколько лет счет сдвинулся на 1 строку, поэтому поражение от Джорджтауна 2: 1 находится на строке выше. Кроме того, когда я добавляю ваш код res.append(result.get_text(strip=True, separator=' ').split(',')) он просто помещает все это между []. Извините, что причиняю боль. Спасибо - person Herman L; 09.01.2020
comment
Привет, Ахмед, извините, что снова беспокою вас, но я не могу понять, что не так в вашем коде. Он работает нормально, но я вижу, что за последние несколько лет счет сдвинулся на 1 строку, поэтому поражение Джорджтауну 2: 1 находится в строке выше - это отображается как победа 1: 0!! . Кроме того, когда я добавляю ваш код res.append(result.get_text(strip=True, separator=' ').split(',')) он просто помещает все это между []. Tryingot отделил W от W, 1-0. Извините, что причиняю боль. Спасибо - person Herman L; 09.01.2020

Несколько вещей:

  1. Вам не нужно перебирать index. Просто пройдитесь по списку
  2. Причина, по которой вы получаете ошибку, заключается в том, что список результатов имеет длину 23, в то время как другие ваши списки имеют длину 24. Таким образом, вам нужно выяснить, как поступать с нулями, и что делать с тем, где они падают (они могут не всегда быть последняя запись)

Как бы я это сделал, я бы брал каждую строку, а затем извлекал данные для этого, а не извлекал каждую сущность в список. Затем я беру все эти строки на сайте, создаю таблицу и составляю список таблиц (по 1 таблице на каждый год). Способ, которым вы можете справиться с отсутствующими данными, — это использовать try/except. Я также добавил небольшую функцию (найденную здесь), которая будет возьмите этот список таблиц и напишите их на отдельных листах Excel.

import requests
import pandas as pd
from pandas import ExcelWriter
from bs4 import BeautifulSoup
#from openpyxl.writer.excel import ExcelWriter
import openpyxl
#from openpyxl import load_workbook
import csv

year_id = ['2019','2018','2017','2016','2015','2014','2013','2012','2011','2010','2009','2008','2007','2006','2005','2004','2003']


results = []
for year in year_id: 
    url = 'https://lehighsports.com/sports/mens-soccer/schedule/' + year
    print (url)
    lehigh = requests.get(url).text
    soup = BeautifulSoup(lehigh,'lxml')

    rows = soup.find_all('div',class_="sidearm-schedule-game-row flex flex-wrap flex-align-center row")

    sheet = pd.DataFrame()
    for row in rows:
        date = row.find('div',class_="sidearm-schedule-game-opponent-date").text.strip()
        name = row.find('div',class_="sidearm-schedule-game-opponent-name").text.strip()
        opp = row.find('div',class_="sidearm-schedule-game-opponent-text").text.strip()
        conf = row.find('div',class_="sidearm-schedule-game-conference-conference").text.strip()

        try:
            result = row.find('div',class_="sidearm-schedule-game-result").text.strip()
        except:
            result = ''

        df = pd.DataFrame([[year,date,name,opp,conf,result]], columns=['year','date','opponent','list','conference','result'])
        sheet = sheet.append(df,sort=True).reset_index(drop=True)

    results.append(sheet)



def save_xls(list_dfs, xls_path):
    with ExcelWriter(xls_path) as writer:
        for n, df in enumerate(list_dfs):
            df.to_excel(writer,'%s' %year_id[n],index=False,)
        writer.save()

save_xls(results,'lehigh.xlsx')
person chitown88    schedule 06.01.2020
comment
как я могу получить год в столбце 1 в excel? - person Herman L; 07.01.2020
comment
Просто включите его в фреймворк данных. Решение отредактировано выше. Обязательно примите это решение. - person chitown88; 08.01.2020
comment
принял решение. Спасибо. Извините, что причиняю боль. Как я могу поместить их все на один лист вместо своих собственных вкладок? Кроме того, как я могу разделить счет (например, T, 2-0) на T и 2-0. Они находятся между отдельными ‹span› T, ‹/span›. Спасибо Читаун88. Очень ценю помощь. - person Herman L; 09.01.2020
comment
Нет боли. Очень простая модификация. Я сделаю их в течение часа и дам вам знать, когда это будет сделано. - person chitown88; 09.01.2020
comment
всем привет. поэтому этот код работает, чтобы разделить счет на 3 столбца. поэтому вместо: try: result = row.find('div',class_=sidearm-schedule-game-result).text.strip() за исключением: result = '' Вместо этого я хотел бы включить это: result = re. findall(r'([AZ]),\s+([\d-]+)\s*(.*)', row.select_one('.sidearm-schedule-game-result').get_text(strip=True , separator=' '))[0] Есть идеи, как это сделать?? Большое спасибо - person Herman L; 10.01.2020
comment
@ chitown88 Куда мне добавить код, чтобы суммировать столбцы на каждом листе? Я предполагаю, что за пределами второго цикла for и до results.append(sheet)? Вот что я хотел бы добавить, более или менее: last_row = ['Total'] + list(sheet.sum())[1:] df2 = pd.DataFrame(data=[last_row], columns=sheet.columns) - person Pfalbaum; 05.02.2021
comment
Надо будет посмотреть чуть позже. Не рядом с моим ноутбуком в данный момент. - person chitown88; 06.02.2021