|
|
import tkinter as tk
|
|
|
import webbrowser
|
|
|
from tkinter import ttk, messagebox
|
|
|
import pandas as pd
|
|
|
import requests
|
|
|
from lxml import etree
|
|
|
from map import map
|
|
|
from line import line
|
|
|
|
|
|
|
|
|
class Home():
|
|
|
def __init__(self):
|
|
|
self.root = tk.Tk()
|
|
|
self.root.title("购房推荐系统")
|
|
|
self.root.geometry("650x350+500+200")
|
|
|
self.Max_index = ''
|
|
|
self.Current_index = 1
|
|
|
self.all_info = []
|
|
|
self.text=''
|
|
|
|
|
|
self.label = tk.Label(self.root, text="欢迎来到北京市购房推荐系统,请选择要查询的地区", font=('宋体', 20), background="#00ffff")
|
|
|
self.label.grid(row=0, column=0, columnspan=4, pady=(20, 0))
|
|
|
|
|
|
self.button_texts = ["海淀", "朝阳", "丰台", "西城", "东城", "昌平", "大兴", "通州", "房山", "顺义", "石景山",
|
|
|
"密云"]
|
|
|
for i, text in enumerate(self.button_texts):
|
|
|
self.button = tk.Button(self.root, text=text, command=lambda txt=text: self.on_button_click(txt))
|
|
|
row = i // 4 + 1
|
|
|
col = i % 4
|
|
|
self.button.grid(row=row, column=col, padx=10, pady=10)
|
|
|
|
|
|
self.btn_map=tk.Button(self.root,text='区位房价',command=self.open_map)
|
|
|
self.btn_map.place(relx=0.65, rely=0.8, relheight=0.10, relwidth=0.13)
|
|
|
|
|
|
self.btn_line=tk.Button(self.root,text="同比房价",command=self.open_line)
|
|
|
self.btn_line.place(relx=0.2, rely=0.8, relheight=0.10, relwidth=0.13)
|
|
|
# 启动窗口事件
|
|
|
self.root.mainloop()
|
|
|
def open_map(self):
|
|
|
map()
|
|
|
webbrowser.open('map.html')
|
|
|
self.clear_csv()
|
|
|
def open_line(self):
|
|
|
line()
|
|
|
webbrowser.open('line.html')
|
|
|
self.clear_csv()
|
|
|
|
|
|
|
|
|
#爬取数据并做匹配
|
|
|
def fetch_data(self,region, index='1'):
|
|
|
url = f"https://newhouse.fang.com/house/s/{region}/b9"+index
|
|
|
response = requests.get(url)
|
|
|
response.encoding = "utf-8"
|
|
|
e = etree.HTML(response.text)
|
|
|
names = [n.strip() for n in e.xpath('//div[@class="nlcd_name"]/a/text()')]
|
|
|
addresses = e.xpath('//div[@class="address"]/a/@title')
|
|
|
prices = [d.xpath('string(.)').strip() for d in e.xpath('//div[@class="nhouse_price"]')]
|
|
|
if index=='1' and self.Max_index=='':
|
|
|
# 从网页获取最大页数
|
|
|
lasts = e.xpath('//a[@class="last"]/@href')
|
|
|
if len(lasts)!=0:
|
|
|
the_string = lasts[-1]
|
|
|
last_char = the_string[-2]
|
|
|
self.Max_index = str(last_char)
|
|
|
else:
|
|
|
return 'False'
|
|
|
|
|
|
for name, address, price in zip(names, addresses, prices):
|
|
|
# 将数据添加到列表中
|
|
|
self.all_info.append((name, price, address))
|
|
|
return self.all_info
|
|
|
|
|
|
|
|
|
# 展示图表数据函数
|
|
|
def show_data_in_table(self,data):
|
|
|
# 创建一个子窗口
|
|
|
self.popup = tk.Toplevel(self.root)
|
|
|
self.popup.geometry('500x500')
|
|
|
self.popup.title("购房信息详情")
|
|
|
|
|
|
# 使用pandas DataFrame处理数据,二维表格数据结构
|
|
|
df = pd.DataFrame(data, columns=["楼盘名称", "价格", "地区"])
|
|
|
# 创建Treeview部件,显式指定列ID
|
|
|
tree = ttk.Treeview(self.popup, columns=("name", "price", "area"), show="headings")
|
|
|
# 设置列标题,使用之前定义的列ID
|
|
|
tree.heading("#1", text="楼盘名称")
|
|
|
tree.heading("#2", text="价格")
|
|
|
tree.heading("#3", text="地区")
|
|
|
# 设置列宽度
|
|
|
tree.column("#1", width=100, anchor='center')
|
|
|
tree.column("#2", width=100, anchor='center')
|
|
|
tree.column("#3", width=100, anchor='center')
|
|
|
|
|
|
# 将DataFrame数据插入Treeview
|
|
|
for index, row in df.iterrows():
|
|
|
tree.insert('', 'end', values=row.tolist())
|
|
|
|
|
|
# 添加垂直滚动条
|
|
|
vsb = ttk.Scrollbar(self.popup, orient="vertical", command=tree.yview)
|
|
|
tree.configure(yscrollcommand=vsb.set)
|
|
|
vsb.pack(side='right', fill='y')
|
|
|
tree.pack(fill='both', expand=True)
|
|
|
|
|
|
# 添加底部框架用于放置翻页按钮
|
|
|
footer_frame = ttk.Frame(self.popup)
|
|
|
footer_frame.pack(side='bottom', fill='x')
|
|
|
|
|
|
footer_frame = ttk.Frame(self.popup)
|
|
|
footer_frame.pack(side='bottom', fill='x')
|
|
|
|
|
|
# 上一页按钮
|
|
|
prev_button = ttk.Button(footer_frame, text="上一页", command=self.go_to_previous_page)
|
|
|
prev_button.pack(side='left', padx=5, pady=5)
|
|
|
|
|
|
# 下一页按钮
|
|
|
next_button = ttk.Button(footer_frame, text="下一页", command=self.go_to_next_page)
|
|
|
next_button.pack(side='right', padx=5, pady=5)
|
|
|
|
|
|
self.center_window()
|
|
|
|
|
|
|
|
|
# 上翻页函数
|
|
|
def go_to_previous_page(self):
|
|
|
if self.Current_index+90 -1 >=91:
|
|
|
self.popup.destroy()
|
|
|
self.Current_index -= 1
|
|
|
print(self.Current_index)
|
|
|
self.all_info.clear()
|
|
|
# 把选择的区域 传入通过fetch传入url
|
|
|
data = self.fetch_data(self.text, str(self.Current_index))
|
|
|
# 网页地址传给展示页面
|
|
|
self.show_data_in_table(data)
|
|
|
else:
|
|
|
messagebox.showinfo(message='这是第一页')
|
|
|
|
|
|
# 下翻页函数
|
|
|
def go_to_next_page(self):
|
|
|
if self.Current_index + 1 <= int(self.Max_index):
|
|
|
self.popup.destroy()
|
|
|
self.Current_index += 1
|
|
|
print(self.Current_index)
|
|
|
self.all_info.clear()
|
|
|
# 把选择的区域 传入通过fetch传入url
|
|
|
data = self.fetch_data(self.text, str(self.Current_index))
|
|
|
# 网页地址传给展示页面
|
|
|
self.show_data_in_table(data)
|
|
|
|
|
|
else:
|
|
|
messagebox.showinfo(message='末尾')
|
|
|
|
|
|
# 首页点击函数
|
|
|
def on_button_click(self,text, index='1'):
|
|
|
self.Max_index = ''
|
|
|
self.Current_index = 1
|
|
|
self.all_info = []
|
|
|
self.text = ''
|
|
|
|
|
|
simplified_text = {
|
|
|
"海淀": "haidian",
|
|
|
"朝阳": "chaoyang",
|
|
|
"丰台": "fengtai",
|
|
|
"西城": "xicheng",
|
|
|
"东城": "dongcheng",
|
|
|
"昌平": "changping",
|
|
|
"大兴": "daxing",
|
|
|
"通州": "tongzhou",
|
|
|
"房山": "fangshan",
|
|
|
"顺义": "shunyi",
|
|
|
"石景山": "shijingshan",
|
|
|
"密云": "miyun",
|
|
|
}.get(text, "未知区域")
|
|
|
self.text=text
|
|
|
|
|
|
if self.fetch_data(simplified_text, index)!="False":
|
|
|
# 把选择的区域 传入通过fetch传入url
|
|
|
data = self.fetch_data(simplified_text, index)
|
|
|
# 获取的数据传给表格
|
|
|
self.show_data_in_table(data)
|
|
|
else:
|
|
|
messagebox.showinfo(message='该地区暂无数据!')
|
|
|
|
|
|
def center_window(self, width=1200, height=600):
|
|
|
# 获取屏幕宽度和高度
|
|
|
screen_width = self.popup.winfo_screenwidth()
|
|
|
screen_height = self.popup.winfo_screenheight()
|
|
|
# 计算窗口的左上角应该放置的位置
|
|
|
left = (screen_width / 2) - (width / 2)
|
|
|
top = (screen_height / 2) - (height / 2)
|
|
|
|
|
|
# 设置窗口的位置和大小
|
|
|
self.popup.geometry("{0}x{1}+{2}+{3}".format(width, height, int(left), int(top)))
|
|
|
|
|
|
def clear_csv(self):
|
|
|
with open('北京市区房价.csv', 'w', encoding='utf-8', newline=''):
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|