Ich habe ein Fenster, das den Nachrichteninhalt in einem Textfeld druckt. Sie müssen zuerst auf die Schaltfläche "Titel anzeigen" klicken, dann den Titel auswählen und schließlich auf die Schaltfläche "Inhalt anzeigen" klicken. Es funktioniert einwandfrei, ohne Probleme.
In dieser Frage habe ich den Fenstercode in einer Klasse einer externen Datei platziert (page1.py)
. Die Datei wird in der Hauptdatei geöffnet (main.py)
. Wenn ich auf die Schaltfläche "Titel anzeigen" klicke, funktioniert es einwandfrei, aber wenn ich auf die Schaltfläche "Inhalt anzeigen" klicke, erhalte ich einen Fehler in der Funktion def content
:
item = df.iloc[selection[-1]]
AttributeError: 'NoneType' object has no attribute 'iloc'
Ich möchte, dass, wenn ich auf die Schaltfläche "Inhalt anzeigen" klicke, der Inhalt der Nachrichten in der Textbox gedruckt wird. Wie ich oben sagte, funktionierte der Code in einer einfachen Datei mit nur einem Fenster perfekt, während ich jetzt Probleme habe, wenn ich ihn in eine externe Klasse einfüge.
Ich bin neu in Python. Können Sie mir den Code in der Antwort zeigen? Sonst verstehe ich es vielleicht nicht, danke und sorry
Main.py
import tkinter as tk
from tkinter import ttk
from PIL import ImageTk
from page1 import Page1
root = tk.Tk()
root.geometry('480x320')
topbar = tk.Frame(root, bg='#e10a0a', height=43)
topbar.pack(fill='x')
style = ttk.Style()
style.theme_use('default') # select a theme that allows configuration of ttk.Notebook
# put the tabs at the left with white background
style.configure('TNotebook', tabposition='wn', background='white', tabmargins=0)
# configure tab with white background initially, yellow background when selected
style.configure('TNotebook.Tab', background='white', width=10, focuscolor='yellow', borderwidth=0)
style.map('TNotebook.Tab', background=[('selected', 'yellow')])
nb = ttk.Notebook(root)
nb.pack(fill='both', expand=1)
page1 = Page1(nb)
nb.add(page1, text='aaaaa', compound='left')
root.mainloop()
Seite1.py
import tkinter as tk
from tkinter import ttk
from tkinter import *
from tkinter import ttk
import tkinter as tk
import tkinter.font as tkFont
from tkinter import ttk
import tkinter as tk # PEP8: `import *` is not preferred
from tkinter import ttk
from tkinter.scrolledtext import ScrolledText
import requests
import requests_cache
from bs4 import BeautifulSoup
import pandas as pd
import re
import json
from dateutil import parser
import datetime
import locale
class Page1(tk.Frame):
def __init__(self, master, **kw):
super().__init__(master, **kw)
def get_data_for(place):
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'
}
results = []
response = requests.get(f'https://www.tuttomercatoweb.com/{place}/', headers=headers)
print('url:', response.url)
print('status:', response.status_code)
#print('html:', response.text[:1000])
soup = BeautifulSoup(response.content, 'html.parser')
#Cover
cover_news = soup.find('div', {'class':'box pp'})
link = cover_news.find('a', href=True)['href']
coverNewsResponse = requests.get(link, headers=headers)
coverSoup = BeautifulSoup(coverNewsResponse.content, 'html.parser')
jsonStr = str(coverSoup.find('script'))
jsonStr = re.search('({.*})', jsonStr).group(1)
jsonData = json.loads(jsonStr)
timePublished = parser.parse(jsonData['datePublished']).strftime("%H:%M")
datePublished = parser.parse(jsonData['datePublished']).strftime("%Y-%m-%d")
title = jsonData['headline']
news = f" {timePublished} {place.upper()}, {title} (TMW)"
results.append( [datePublished, timePublished, place, title, news, link] )
# Side panel
side_news = soup.find_all('div', {'class':'box small'})
for each in side_news:
link = each.find('a', href=True)['href']
sideNewsResponse = requests.get(link, headers=headers)
sideSoup = BeautifulSoup(sideNewsResponse.content, 'html.parser')
jsonStr = str(sideSoup.find('script'))
jsonStr = re.search('({.*})', jsonStr).group(1)
jsonData = json.loads(jsonStr)
timePublished = parser.parse(jsonData['datePublished']).strftime("%H:%M")
datePublished = parser.parse(jsonData['datePublished']).strftime("%Y-%m-%d")
title = jsonData['headline']
news = f" {timePublished} {place.upper()}, {title} (TMW)"
results.append( [datePublished, timePublished, place, title, news, link] )
news = soup.find_all('div', attrs={"class": "tcc-list-news"})
for each in news:
for div in each.find_all("div"):
timePublished = div.find('span', attrs={'class': 'hh serif'}).text
datePublished = div.find_previous('div', {'class':'tcc-border upper date'})
if datePublished:
if datePublished.text in ['Ieri']:
yesterday = datetime.datetime.today() - datetime.timedelta(days = 1)
datePublished = yesterday.strftime("%Y-%m-%d")
else:
locale.setlocale(locale.LC_ALL, '') #locale.setlocale(locale.LC_ALL, 'it')
currentYear = datetime.datetime.today().strftime("%Y")
dateStr = datePublished.text
dateStr = datetime.datetime.strptime(dateStr + ' ' + currentYear, '%A %d %B %Y')
datePublished = dateStr.strftime("%Y-%m-%d")
else:
datePublished = datetime.datetime.today().strftime("%Y-%m-%d")
title = " ".join(span.text for span in div.select("a > span"))
news = f" {timePublished} {place.upper()}, {title} (TMW)"
link = div.find('a')['href']
results.append( [datePublished, timePublished, place, title, news, link] )
return results
def all_titles():
global df
allnews = [] # local variable
for place in ['atalanta', 'bologna']:
print('search:', place)
results = get_data_for(place)
print('found:', len(results))
allnews += results
text_download.insert('end', f"search: {place}\nfound: {len(results)}\n")
df = pd.DataFrame(allnews, columns=['date', 'time', 'place', 'title', 'news', 'link'])
df = df.sort_values(by=['date', 'time', 'place', 'title'], ascending=[False, False, True, True])
df = df.drop_duplicates(subset=['date', 'time', 'place', 'title'])
df = df.reset_index(drop=True)
listbox_title.delete('0', 'end')
for index, row in df.iterrows():
listbox_title.insert('end', row['news'])
def content(event=None): # `command=` executes without `event`, but `bind` executes with `event` - so it needs default value
# tuple
selection = listbox_title.curselection()
print('selection:', selection)
if selection:
item = df.iloc[selection[-1]]
#print('item:', item)
url = item['link']
#print('url:', url)
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'
}
# keep page in database `SQLite`
# https://github.com/reclosedev/requests-cache
# https://sqlite.org/index.html
session = requests_cache.CachedSession('titles')
response = session.get(url, headers=headers)
#response = requests.get(url, headers=headers)
soup = BeautifulSoup(response.content, 'html.parser')
content_download = "\n".join(item.get_text() for item in soup.select("div.text.mbottom"))
text_download.delete('1.0', 'end') # remove previous content)
text_download.insert('end', content_download)
# --- main ---
df = None
# window = tk.Tk()
# window.geometry("800x800")
frame_title = tk.Frame(self)
frame_title.pack(fill='both', expand=True, pady=5, padx=5)
listbox_title = tk.Listbox(frame_title, selectbackground="#960000", selectforeground="white", bg="white")
listbox_title.pack(side='left', fill='both', expand=True)
scrollbar_title = tk.Scrollbar(frame_title)
scrollbar_title.pack(side='left', fill='y')
scrollbar_title['command'] = listbox_title.yview
listbox_title.config(yscrollcommand=scrollbar_title.set)
listbox_title.bind('<Double-Button-1>', content) # it executes `content(event)`
# ----
text_download = ScrolledText(self, bg="white")
text_download.pack(fill='both', expand=True, pady=0, padx=5)
# ----
buttons_frame = tk.Frame(self)
buttons_frame.pack(fill='x')
button1 = tk.Button(buttons_frame, text="View Titles", command=all_titles) # don't use `[]` to execute functions
button1.pack(side='left', pady=5, padx=5)
button2 = tk.Button(buttons_frame, text="View Content", command=content) # don't use `[]` to execute functions
button2.pack(side='left', pady=5, padx=(0,5))
Lösung des Problems
Ich denke, Sie haben df
in einer der Funktionen, die unter Ihrer __init__
Methode verschachtelt sind, eine globale Variable deklariert... und später in Ihrem Hauptabschnitt, der tatsächlich in ausgeführt wird, auf __init__
gesetzt. Sie sollten viel vorsichtiger sein, wenn es darum geht, Variablen global zu machen, und ein bisschen mehr über den Funktionsbereich nachdenken. Müssen diese Funktionen, die Sie definieren, im Geltungsbereich von liegen, oder können sie einen anderen Geltungsbereich haben?df
None
__init__
Keine Kommentare:
Kommentar veröffentlichen