Stack Overflow на русском Asked by Genken on November 7, 2021
Стоит задача, спарсить (с парсингом проблем нет) несколько однообразных страничек и записать полученные данные в таблицу, причём во время парсинга каждой из страничек мы должны создать словарь, из него DataFrame, и этот DataFrame записать в отдельный лист в .xlsx книге, после чего операция повторяется.
Если нужно обработать лишь одну страничку всё нормально. Но если их несколько, возникает одна проблема: новые листы не создаются. Вместо этого, DataFrame записываются в один и тот же лист (также странно, что в конечном файле остаётся не последний DataFrame, а ВСЕ DataFrame, несмотря на то, что xlsxwriter режим append
не поддерживает и в теории должен делать перезапись), и этот лист имеет название последней итерируемой странички.
Скорее всего это происходит, потому что используется один и тот же DataFrame (под именем database
), имя которого не меняется и он просто обнуляется при анализе новой страницы, но я не уверен – если создать его копию, она по-прежнему записывается в один и тот же лист (хотя это может быть из-за того что я оставлял ссылку на один и тот же DataFrame, пытаясь оставить копию). Вряд ли xlsxwriter сохраняет по принципу "Сохранять в один и тот же лист, если имя DataFrame не меняется"
Код:
from bs4 import BeautifulSoup
from pandas import ExcelWriter
import pandas as pd
import os
import xlsxwriter
def nametreat(txt): # Это функции для обработки текста
if txt[-1] == ')':
bracktxt = ''
i = 1
while txt[-i] != '(':
bracktxt += txt[-i]
i += 1
bracktxt = bracktxt[::-1]
if 'класс' in bracktxt:
while txt[-1] != '(':
txt = txt[0:-1:1]
return txt[0:-2:1]
else:
return txt
def spaceclear(txt): # Это функция для обработки текста
while len(txt) > 0 and (txt[0] == ' ' or txt[0] == 'n'):
txt = txt[1:]
while len(txt) > 0 and (txt[-1] == ' ' or txt[-1] == 'n'):
txt = txt[0:-1]
return txt
def courseinfo(bs):
clss_, times, month = bs.find_all('div', attrs = {'class': "course__info-item"})
clss_, times, month = map(spaceclear, [clss_.text, times.text, month.text])
nums = '0123456789'
while clss_[-1] not in nums:
clss_ = clss_[0:-1:1]
if '-' not in clss_:
start = int(clss_)
end = start
else:
start, end = map(int, clss_.split('-'))
clss_ = list(range(start, end + 1))
while times[-1] not in nums:
times = times[0:-1:1]
times = [int(times[0]), int(times[-1])]
month = list(month.split('-'))
res = [clss_, times, month]
return res
science = open('schools_science.html', encoding = 'utf-8', mode = 'r')
sport = open('schools_sport.html', encoding = 'utf-8', mode = 'r')
creative = open('schools_creative.html', encoding = 'utf-8', mode = 'r')
teaming = open('schools_teaming.html', encoding = 'utf-8', mode = 'r')
responsib = open('schools_responsib.html', encoding = 'utf-8', mode = 'r')
files = [science, sport, teaming, creative, responsib]
maindict = {
'name': [],
'type': [],
'description': [],
'text': [],
'grades': [],
'times_a_week': [],
'lessons': [],
'from_month': [],
'to_month': []
}
database = pd.DataFrame(maindict)
tablist = ['Science', 'Sport', 'Creative', 'Teaming', 'Responsibility']
tab = 0
for file in files:
soup = BeautifulSoup(file, 'lxml')
courses = soup.find_all("div", attrs = {'class': "courses-list__item"})
for cl in courses:
maindict['type'].append(spaceclear(cl.find("div", attrs = {'class': "course__desc"}).text))
maindict['name'].append(nametreat(spaceclear(cl.find("h2").text)))
maindict['description'].append(spaceclear(cl.find("div", attrs = {'class': "course__big-text"}).text))
maindict['text'].append(spaceclear(cl.find("div", attrs = {'class': "course__small-text"}).find("p").text))
clss_, times, month = map(spaceclear, courseinfo(cl))
maindict['grades'].append(clss_)
maindict['times_a_week'].append(times[0])
maindict['lessons'].append(times[1])
maindict['from_month'].append(month[0])
maindict['to_month'].append(month[1])
database = pd.DataFrame(maindict)
with ExcelWriter(path = 'schools.xlsx', engine = 'xlsxwriter') as writer:
database.to_excel(writer, sheet_name = tablist[tab], index = False)
writer.save()
tab += 1
exit(0)
Используя XlsxWriter можно создать новый excel файл с несколькими листами - пример:
import pandas as pd
# Create some Pandas dataframes from some data.
df1 = pd.DataFrame({'Data': [11, 12, 13, 14]})
df2 = pd.DataFrame({'Data': [21, 22, 23, 24]})
df3 = pd.DataFrame({'Data': [31, 32, 33, 34]})
# Create a Pandas Excel writer using XlsxWriter as the engine.
writer = pd.ExcelWriter('pandas_multiple.xlsx', engine='xlsxwriter')
# Write each dataframe to a different worksheet.
df1.to_excel(writer, sheet_name='Sheet1')
df2.to_excel(writer, sheet_name='Sheet2')
df3.to_excel(writer, sheet_name='Sheet3')
# Close the Pandas Excel writer and output the Excel file.
writer.save()
Для того, чтобы дописывать данные в существующий Excel файл, можно воспользоваться функцией append_df_to_excel()
:
append_df_to_excel('d:/temp/test.xlsx', df, sheet_name='Sheet2', index=False)
append_df_to_excel('d:/temp/test.xlsx', df, sheet_name='Sheet3', index=False)
Answered by MaxU on November 7, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP