You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

203 lines
7.2 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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