|
|
|
|
@ -13,6 +13,9 @@ from datetime import datetime
|
|
|
|
|
class WordRibbonTab(QWidget):
|
|
|
|
|
def __init__(self, parent=None):
|
|
|
|
|
super().__init__(parent)
|
|
|
|
|
self.weather_group = None # 天气组件组
|
|
|
|
|
self.weather_visible = False # 天气组件显示状态
|
|
|
|
|
self.ribbon_layout = None # 功能区布局
|
|
|
|
|
self.setup_ui()
|
|
|
|
|
|
|
|
|
|
def setup_ui(self):
|
|
|
|
|
@ -24,6 +27,11 @@ class WordRibbonTab(QWidget):
|
|
|
|
|
class WordRibbon(QFrame):
|
|
|
|
|
def __init__(self, parent=None):
|
|
|
|
|
super().__init__(parent)
|
|
|
|
|
self.weather_visible = False # 天气组件显示状态
|
|
|
|
|
self.weather_group = None # 天气组件组
|
|
|
|
|
self.quote_visible = False # 每日一言组件显示状态
|
|
|
|
|
self.quote_group = None # 每日一言组件组
|
|
|
|
|
self.ribbon_layout = None # 功能区布局
|
|
|
|
|
self.setup_ui()
|
|
|
|
|
|
|
|
|
|
def setup_ui(self):
|
|
|
|
|
@ -45,35 +53,16 @@ class WordRibbon(QFrame):
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
|
|
|
|
|
ribbon_layout = QHBoxLayout()
|
|
|
|
|
ribbon_layout.setContentsMargins(10, 5, 10, 5)
|
|
|
|
|
ribbon_layout.setSpacing(15)
|
|
|
|
|
self.ribbon_layout = QHBoxLayout() # 保存为实例变量
|
|
|
|
|
self.ribbon_layout.setContentsMargins(10, 5, 10, 5)
|
|
|
|
|
self.ribbon_layout.setSpacing(15)
|
|
|
|
|
|
|
|
|
|
# 开始标签的内容(最常用的功能)
|
|
|
|
|
self.setup_home_tab(ribbon_layout)
|
|
|
|
|
self.setup_home_tab(self.ribbon_layout)
|
|
|
|
|
|
|
|
|
|
# 添加天气工具组
|
|
|
|
|
weather_group = self.create_ribbon_group("天气")
|
|
|
|
|
weather_layout = QVBoxLayout()
|
|
|
|
|
# 天气工具组将在需要时动态添加
|
|
|
|
|
|
|
|
|
|
# 城市选择
|
|
|
|
|
self.city_combo = QComboBox()
|
|
|
|
|
self.city_combo.setFixedWidth(100)
|
|
|
|
|
self.city_combo.addItems(['自动定位', '北京', '上海', '广州', '深圳', '杭州', '南京', '武汉', '成都', '西安'])
|
|
|
|
|
self.city_combo.setCurrentText('自动定位')
|
|
|
|
|
self.city_combo.currentTextChanged.connect(self.on_city_changed)
|
|
|
|
|
|
|
|
|
|
# 刷新按钮
|
|
|
|
|
self.refresh_weather_btn = QPushButton("刷新天气")
|
|
|
|
|
self.refresh_weather_btn.clicked.connect(self.on_refresh_weather)
|
|
|
|
|
self.refresh_weather_btn.setFixedSize(80, 25)
|
|
|
|
|
|
|
|
|
|
weather_layout.addWidget(self.city_combo)
|
|
|
|
|
weather_layout.addWidget(self.refresh_weather_btn)
|
|
|
|
|
weather_group.setLayout(weather_layout)
|
|
|
|
|
ribbon_layout.addWidget(weather_group)
|
|
|
|
|
|
|
|
|
|
self.ribbon_area.setLayout(ribbon_layout)
|
|
|
|
|
self.ribbon_area.setLayout(self.ribbon_layout)
|
|
|
|
|
|
|
|
|
|
main_layout.addWidget(self.ribbon_area)
|
|
|
|
|
self.setLayout(main_layout)
|
|
|
|
|
@ -179,6 +168,105 @@ class WordRibbon(QFrame):
|
|
|
|
|
"""下划线按钮点击处理"""
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def create_weather_group(self):
|
|
|
|
|
"""创建天气组件组"""
|
|
|
|
|
if self.weather_group is not None:
|
|
|
|
|
return self.weather_group
|
|
|
|
|
|
|
|
|
|
weather_group = self.create_ribbon_group("天气")
|
|
|
|
|
weather_layout = QVBoxLayout()
|
|
|
|
|
|
|
|
|
|
# 城市选择 - 添加所有省会城市
|
|
|
|
|
self.city_combo = QComboBox()
|
|
|
|
|
self.city_combo.setFixedWidth(120) # 增加宽度以显示完整城市名
|
|
|
|
|
self.city_combo.addItems([
|
|
|
|
|
'自动定位',
|
|
|
|
|
'北京', '上海', '广州', '深圳', '杭州', '南京', '武汉', '成都', '西安', # 一线城市
|
|
|
|
|
'天津', '重庆', '苏州', '青岛', '大连', '宁波', '厦门', '无锡', '佛山', # 新一线城市
|
|
|
|
|
'石家庄', '太原', '呼和浩特', '沈阳', '长春', '哈尔滨', # 东北华北
|
|
|
|
|
'合肥', '福州', '南昌', '济南', '郑州', '长沙', '南宁', '海口', # 华东华中华南
|
|
|
|
|
'贵阳', '昆明', '拉萨', '兰州', '西宁', '银川', '乌鲁木齐' # 西南西北
|
|
|
|
|
])
|
|
|
|
|
self.city_combo.setCurrentText('自动定位')
|
|
|
|
|
self.city_combo.currentTextChanged.connect(self.on_city_changed)
|
|
|
|
|
|
|
|
|
|
# 刷新按钮
|
|
|
|
|
self.refresh_weather_btn = QPushButton("刷新天气")
|
|
|
|
|
self.refresh_weather_btn.clicked.connect(self.on_refresh_weather)
|
|
|
|
|
self.refresh_weather_btn.setFixedSize(80, 25)
|
|
|
|
|
|
|
|
|
|
weather_layout.addWidget(self.city_combo)
|
|
|
|
|
weather_layout.addWidget(self.refresh_weather_btn)
|
|
|
|
|
weather_group.setLayout(weather_layout)
|
|
|
|
|
|
|
|
|
|
self.weather_group = weather_group
|
|
|
|
|
return weather_group
|
|
|
|
|
|
|
|
|
|
def show_weather_group(self):
|
|
|
|
|
"""显示天气组件"""
|
|
|
|
|
if not self.weather_visible and self.weather_group is None:
|
|
|
|
|
weather_group = self.create_weather_group()
|
|
|
|
|
# 在编辑组之后添加天气组
|
|
|
|
|
if self.ribbon_layout:
|
|
|
|
|
# 找到编辑组的位置,在其后插入天气组
|
|
|
|
|
insert_index = self.ribbon_layout.count() - 1 # 在stretch之前插入
|
|
|
|
|
self.ribbon_layout.insertWidget(insert_index, weather_group)
|
|
|
|
|
self.weather_visible = True
|
|
|
|
|
|
|
|
|
|
def hide_weather_group(self):
|
|
|
|
|
"""隐藏天气组件"""
|
|
|
|
|
if self.weather_visible and self.weather_group is not None:
|
|
|
|
|
self.weather_group.setParent(None)
|
|
|
|
|
self.weather_group = None
|
|
|
|
|
self.weather_visible = False
|
|
|
|
|
|
|
|
|
|
def create_quote_group(self):
|
|
|
|
|
"""创建每日一言组件组"""
|
|
|
|
|
if self.quote_group is not None:
|
|
|
|
|
return self.quote_group
|
|
|
|
|
|
|
|
|
|
quote_group = self.create_ribbon_group("每日一言")
|
|
|
|
|
quote_layout = QVBoxLayout()
|
|
|
|
|
|
|
|
|
|
# 每日一言显示标签
|
|
|
|
|
self.quote_label = QLabel("每日一言: 暂无")
|
|
|
|
|
self.quote_label.setStyleSheet("QLabel { color: #666666; font-style: italic; font-size: 10px; }")
|
|
|
|
|
self.quote_label.setWordWrap(True)
|
|
|
|
|
self.quote_label.setFixedWidth(150)
|
|
|
|
|
|
|
|
|
|
# 刷新按钮
|
|
|
|
|
self.refresh_quote_btn = QPushButton("刷新箴言")
|
|
|
|
|
self.refresh_quote_btn.clicked.connect(self.on_refresh_quote)
|
|
|
|
|
self.refresh_quote_btn.setFixedSize(80, 25)
|
|
|
|
|
|
|
|
|
|
quote_layout.addWidget(self.quote_label)
|
|
|
|
|
quote_layout.addWidget(self.refresh_quote_btn)
|
|
|
|
|
quote_group.setLayout(quote_layout)
|
|
|
|
|
|
|
|
|
|
self.quote_group = quote_group
|
|
|
|
|
return quote_group
|
|
|
|
|
|
|
|
|
|
def show_quote_group(self):
|
|
|
|
|
"""显示每日一言组件"""
|
|
|
|
|
if not self.quote_visible and self.quote_group is None:
|
|
|
|
|
quote_group = self.create_quote_group()
|
|
|
|
|
# 在天气组之后添加每日一言组
|
|
|
|
|
if self.ribbon_layout:
|
|
|
|
|
# 找到合适的位置插入每日言组
|
|
|
|
|
insert_index = self.ribbon_layout.count() - 1 # 在stretch之前插入
|
|
|
|
|
# 如果天气组件存在,在其后插入;否则在编辑组后插入
|
|
|
|
|
if self.weather_group is not None and self.weather_visible:
|
|
|
|
|
insert_index = self.ribbon_layout.indexOf(self.weather_group) + 1
|
|
|
|
|
self.ribbon_layout.insertWidget(insert_index, quote_group)
|
|
|
|
|
self.quote_visible = True
|
|
|
|
|
|
|
|
|
|
def hide_quote_group(self):
|
|
|
|
|
"""隐藏每日一言组件"""
|
|
|
|
|
if self.quote_visible and self.quote_group is not None:
|
|
|
|
|
self.quote_group.setParent(None)
|
|
|
|
|
self.quote_group = None
|
|
|
|
|
self.quote_visible = False
|
|
|
|
|
|
|
|
|
|
def create_ribbon_group(self, title):
|
|
|
|
|
"""创建功能区组"""
|
|
|
|
|
group = QGroupBox(title)
|
|
|
|
|
@ -208,6 +296,15 @@ class WordRibbon(QFrame):
|
|
|
|
|
"""城市选择变化处理"""
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def on_refresh_quote(self):
|
|
|
|
|
"""刷新每日一言按钮点击处理"""
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def update_quote_display(self, quote_text):
|
|
|
|
|
"""更新每日一言显示"""
|
|
|
|
|
if hasattr(self, 'quote_label') and self.quote_label:
|
|
|
|
|
self.quote_label.setText(f"每日一言: {quote_text}")
|
|
|
|
|
|
|
|
|
|
def create_ribbon_button(self, text, shortcut, icon_name):
|
|
|
|
|
"""创建功能区按钮"""
|
|
|
|
|
btn = QToolButton()
|
|
|
|
|
@ -575,6 +672,24 @@ class WeatherAPI:
|
|
|
|
|
results[city] = weather_data
|
|
|
|
|
return results
|
|
|
|
|
|
|
|
|
|
def get_isp_info(self):
|
|
|
|
|
"""获取ISP信息"""
|
|
|
|
|
try:
|
|
|
|
|
url = "http://ip-api.com/json/"
|
|
|
|
|
response = requests.get(url, timeout=5)
|
|
|
|
|
response.raise_for_status()
|
|
|
|
|
|
|
|
|
|
data = response.json()
|
|
|
|
|
if data.get('status') == 'success':
|
|
|
|
|
isp = data.get('isp', '')
|
|
|
|
|
org = data.get('org', '')
|
|
|
|
|
as_info = data.get('as', '')
|
|
|
|
|
return f"{isp} {org} {as_info}".strip()
|
|
|
|
|
return None
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"获取ISP信息失败: {e}")
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
def get_location_by_ip(self):
|
|
|
|
|
"""通过IP地址获取用户位置"""
|
|
|
|
|
try:
|
|
|
|
|
@ -675,12 +790,159 @@ class WeatherAPI:
|
|
|
|
|
city = self.get_location_by_ip()
|
|
|
|
|
if city:
|
|
|
|
|
print(f"通过IP定位成功: {city}")
|
|
|
|
|
|
|
|
|
|
# 检查是否是教育网或特殊网络环境
|
|
|
|
|
isp_info = self.get_isp_info()
|
|
|
|
|
if isp_info and ('教育网' in isp_info or 'CERNET' in isp_info or 'University' in isp_info):
|
|
|
|
|
print(f"检测到教育网环境: {isp_info}")
|
|
|
|
|
print("教育网IP定位可能不准确,建议手动选择城市")
|
|
|
|
|
# 教育网环境下,如果定位到北京,可能是IP分配问题
|
|
|
|
|
if city.lower() in ['beijing', '北京', 'haidian', '海淀']:
|
|
|
|
|
print("提示:教育网环境下北京定位可能是网络出口导致的")
|
|
|
|
|
return {'city': city, 'note': '教育网环境,定位可能不准确', 'isp': isp_info}
|
|
|
|
|
|
|
|
|
|
# 智能处理 - 如果是区级单位,映射到市级城市
|
|
|
|
|
district_to_city_map = {
|
|
|
|
|
# 北京各区
|
|
|
|
|
'海淀': '北京',
|
|
|
|
|
'haidian': '北京',
|
|
|
|
|
'朝阳': '北京',
|
|
|
|
|
'chaoyang': '北京',
|
|
|
|
|
'东城': '北京',
|
|
|
|
|
'dongcheng': '北京',
|
|
|
|
|
'西城': '北京',
|
|
|
|
|
'xicheng': '北京',
|
|
|
|
|
'丰台': '北京',
|
|
|
|
|
'fengtai': '北京',
|
|
|
|
|
'石景山': '北京',
|
|
|
|
|
'shijingshan': '北京',
|
|
|
|
|
'通州': '北京',
|
|
|
|
|
'tongzhou': '北京',
|
|
|
|
|
'昌平': '北京',
|
|
|
|
|
'changping': '北京',
|
|
|
|
|
'大兴': '北京',
|
|
|
|
|
'daxing': '北京',
|
|
|
|
|
'怀柔': '北京',
|
|
|
|
|
'huairou': '北京',
|
|
|
|
|
'平谷': '北京',
|
|
|
|
|
'pinggu': '北京',
|
|
|
|
|
'门头沟': '北京',
|
|
|
|
|
'mentougou': '北京',
|
|
|
|
|
'密云': '北京',
|
|
|
|
|
'miyun': '北京',
|
|
|
|
|
'延庆': '北京',
|
|
|
|
|
'yanqing': '北京',
|
|
|
|
|
'房山': '北京',
|
|
|
|
|
'fangshan': '北京',
|
|
|
|
|
'顺义': '北京',
|
|
|
|
|
'shunyi': '北京',
|
|
|
|
|
|
|
|
|
|
# 天津各区
|
|
|
|
|
'和平': '天津',
|
|
|
|
|
'heping': '天津',
|
|
|
|
|
'河东': '天津',
|
|
|
|
|
'hedong': '天津',
|
|
|
|
|
'河西': '天津',
|
|
|
|
|
'hexi': '天津',
|
|
|
|
|
'南开': '天津',
|
|
|
|
|
'nankai': '天津',
|
|
|
|
|
'河北': '天津',
|
|
|
|
|
'hebei': '天津',
|
|
|
|
|
'红桥': '天津',
|
|
|
|
|
'hongqiao': '天津',
|
|
|
|
|
'滨海新区': '天津',
|
|
|
|
|
'binhaixinqu': '天津',
|
|
|
|
|
'东丽': '天津',
|
|
|
|
|
'dongli': '天津',
|
|
|
|
|
'西青': '天津',
|
|
|
|
|
'xiqing': '天津',
|
|
|
|
|
'津南': '天津',
|
|
|
|
|
'jinnan': '天津',
|
|
|
|
|
'北辰': '天津',
|
|
|
|
|
'beichen': '天津',
|
|
|
|
|
'武清': '天津',
|
|
|
|
|
'wuqing': '天津',
|
|
|
|
|
'宝坻': '天津',
|
|
|
|
|
'baodi': '天津',
|
|
|
|
|
'宁河': '天津',
|
|
|
|
|
'ninghe': '天津',
|
|
|
|
|
'静海': '天津',
|
|
|
|
|
'jinghai': '天津',
|
|
|
|
|
'蓟州': '天津',
|
|
|
|
|
'jizhou': '天津',
|
|
|
|
|
|
|
|
|
|
# 上海各区
|
|
|
|
|
'黄浦': '上海',
|
|
|
|
|
'huangpu': '上海',
|
|
|
|
|
'徐汇': '上海',
|
|
|
|
|
'xuhui': '上海',
|
|
|
|
|
'长宁': '上海',
|
|
|
|
|
'changning': '上海',
|
|
|
|
|
'静安': '上海',
|
|
|
|
|
'jingan': '上海',
|
|
|
|
|
'普陀': '上海',
|
|
|
|
|
'putuo': '上海',
|
|
|
|
|
'虹口': '上海',
|
|
|
|
|
'hongkou': '上海',
|
|
|
|
|
'杨浦': '上海',
|
|
|
|
|
'yangpu': '上海',
|
|
|
|
|
'闵行': '上海',
|
|
|
|
|
'minhang': '上海',
|
|
|
|
|
'宝山': '上海',
|
|
|
|
|
'baoshan': '上海',
|
|
|
|
|
'嘉定': '上海',
|
|
|
|
|
'jiading': '上海',
|
|
|
|
|
'浦东': '上海',
|
|
|
|
|
'pudong': '上海',
|
|
|
|
|
'金山': '上海',
|
|
|
|
|
'jinshan': '上海',
|
|
|
|
|
'松江': '上海',
|
|
|
|
|
'songjiang': '上海',
|
|
|
|
|
'青浦': '上海',
|
|
|
|
|
'qingpu': '上海',
|
|
|
|
|
'奉贤': '上海',
|
|
|
|
|
'fengxian': '上海',
|
|
|
|
|
'崇明': '上海',
|
|
|
|
|
'chongming': '上海',
|
|
|
|
|
|
|
|
|
|
# 广州各区
|
|
|
|
|
'天河': '广州',
|
|
|
|
|
'tianhe': '广州',
|
|
|
|
|
'越秀': '广州',
|
|
|
|
|
'yuexiu': '广州',
|
|
|
|
|
'海珠': '广州',
|
|
|
|
|
'haizhu': '广州',
|
|
|
|
|
'荔湾': '广州',
|
|
|
|
|
'liwan': '广州',
|
|
|
|
|
'白云': '广州',
|
|
|
|
|
'baiyun': '广州',
|
|
|
|
|
'黄埔': '广州',
|
|
|
|
|
'huangpu': '广州',
|
|
|
|
|
'番禺': '广州',
|
|
|
|
|
'panyu': '广州',
|
|
|
|
|
'花都': '广州',
|
|
|
|
|
'huadu': '广州',
|
|
|
|
|
'南沙': '广州',
|
|
|
|
|
'nansha': '广州',
|
|
|
|
|
'从化': '广州',
|
|
|
|
|
'conghua': '广州',
|
|
|
|
|
'增城': '广州',
|
|
|
|
|
'zengcheng': '广州'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# 检查是否是区级单位,如果是则映射到市级城市
|
|
|
|
|
city_lower = city.lower()
|
|
|
|
|
if city_lower in district_to_city_map:
|
|
|
|
|
mapped_city = district_to_city_map[city_lower]
|
|
|
|
|
print(f"智能映射: {city} -> {mapped_city}")
|
|
|
|
|
city = mapped_city
|
|
|
|
|
|
|
|
|
|
return {'city': city}
|
|
|
|
|
|
|
|
|
|
# 如果IP定位失败,尝试其他方法
|
|
|
|
|
# 可以尝试使用浏览器的地理位置API,但这需要前端支持
|
|
|
|
|
|
|
|
|
|
print("自动定位失败,使用默认城市")
|
|
|
|
|
print("自动定位失败,建议手动选择城市")
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
@ -692,6 +954,138 @@ class WeatherAPI:
|
|
|
|
|
try:
|
|
|
|
|
# 处理英文城市名映射
|
|
|
|
|
original_city_name = city_name
|
|
|
|
|
|
|
|
|
|
# 智能城市映射 - 将区级单位映射到市级城市
|
|
|
|
|
district_to_city_map = {
|
|
|
|
|
# 北京各区
|
|
|
|
|
'海淀': '北京',
|
|
|
|
|
'朝阳': '北京',
|
|
|
|
|
'东城': '北京',
|
|
|
|
|
'西城': '北京',
|
|
|
|
|
'丰台': '北京',
|
|
|
|
|
'石景山': '北京',
|
|
|
|
|
'通州': '北京',
|
|
|
|
|
'昌平': '北京',
|
|
|
|
|
'大兴': '北京',
|
|
|
|
|
'怀柔': '北京',
|
|
|
|
|
'平谷': '北京',
|
|
|
|
|
'门头沟': '北京',
|
|
|
|
|
'密云': '北京',
|
|
|
|
|
'延庆': '北京',
|
|
|
|
|
'房山': '北京',
|
|
|
|
|
'顺义': '北京',
|
|
|
|
|
'haidian': '北京',
|
|
|
|
|
'chaoyang': '北京',
|
|
|
|
|
'dongcheng': '北京',
|
|
|
|
|
'xicheng': '北京',
|
|
|
|
|
'fengtai': '北京',
|
|
|
|
|
'shijingshan': '北京',
|
|
|
|
|
'tongzhou': '北京',
|
|
|
|
|
'changping': '北京',
|
|
|
|
|
'daxing': '北京',
|
|
|
|
|
'huairou': '北京',
|
|
|
|
|
'pinggu': '北京',
|
|
|
|
|
'mentougou': '北京',
|
|
|
|
|
'miyun': '北京',
|
|
|
|
|
'yanqing': '北京',
|
|
|
|
|
'fangshan': '北京',
|
|
|
|
|
'shunyi': '北京',
|
|
|
|
|
|
|
|
|
|
# 天津各区(统一映射到天津)
|
|
|
|
|
'和平': '天津',
|
|
|
|
|
'heping': '天津',
|
|
|
|
|
'河东': '天津',
|
|
|
|
|
'hedong': '天津',
|
|
|
|
|
'河西': '天津',
|
|
|
|
|
'hexi': '天津',
|
|
|
|
|
'南开': '天津',
|
|
|
|
|
'nankai': '天津',
|
|
|
|
|
'河北': '天津',
|
|
|
|
|
'红桥': '天津',
|
|
|
|
|
'hongqiao': '天津',
|
|
|
|
|
'滨海新区': '天津',
|
|
|
|
|
'binhaixinqu': '天津',
|
|
|
|
|
'东丽': '天津',
|
|
|
|
|
'dongli': '天津',
|
|
|
|
|
'西青': '天津',
|
|
|
|
|
'xiqing': '天津',
|
|
|
|
|
'津南': '天津',
|
|
|
|
|
'jinnan': '天津',
|
|
|
|
|
'北辰': '天津',
|
|
|
|
|
'beichen': '天津',
|
|
|
|
|
'武清': '天津',
|
|
|
|
|
'wuqing': '天津',
|
|
|
|
|
'宝坻': '天津',
|
|
|
|
|
'baodi': '天津',
|
|
|
|
|
'宁河': '天津',
|
|
|
|
|
'ninghe': '天津',
|
|
|
|
|
'静海': '天津',
|
|
|
|
|
'jinghai': '天津',
|
|
|
|
|
'蓟州': '天津',
|
|
|
|
|
'jizhou': '天津',
|
|
|
|
|
'黄浦': '上海',
|
|
|
|
|
'徐汇': '上海',
|
|
|
|
|
'长宁': '上海',
|
|
|
|
|
'静安': '上海',
|
|
|
|
|
'普陀': '上海',
|
|
|
|
|
'虹口': '上海',
|
|
|
|
|
'杨浦': '上海',
|
|
|
|
|
'闵行': '上海',
|
|
|
|
|
'宝山': '上海',
|
|
|
|
|
'嘉定': '上海',
|
|
|
|
|
'浦东': '上海',
|
|
|
|
|
'金山': '上海',
|
|
|
|
|
'松江': '上海',
|
|
|
|
|
'青浦': '上海',
|
|
|
|
|
'奉贤': '上海',
|
|
|
|
|
'崇明': '上海',
|
|
|
|
|
'huangpu': '上海',
|
|
|
|
|
'xuhui': '上海',
|
|
|
|
|
'changning': '上海',
|
|
|
|
|
'jingan': '上海',
|
|
|
|
|
'putuo': '上海',
|
|
|
|
|
'hongkou': '上海',
|
|
|
|
|
'yangpu': '上海',
|
|
|
|
|
'minhang': '上海',
|
|
|
|
|
'baoshan': '上海',
|
|
|
|
|
'jiading': '上海',
|
|
|
|
|
'pudong': '上海',
|
|
|
|
|
'jinshan': '上海',
|
|
|
|
|
'songjiang': '上海',
|
|
|
|
|
'qingpu': '上海',
|
|
|
|
|
'fengxian': '上海',
|
|
|
|
|
'chongming': '上海',
|
|
|
|
|
'天河': '广州',
|
|
|
|
|
'越秀': '广州',
|
|
|
|
|
'海珠': '广州',
|
|
|
|
|
'荔湾': '广州',
|
|
|
|
|
'白云': '广州',
|
|
|
|
|
'黄埔': '广州',
|
|
|
|
|
'番禺': '广州',
|
|
|
|
|
'花都': '广州',
|
|
|
|
|
'南沙': '广州',
|
|
|
|
|
'从化': '广州',
|
|
|
|
|
'增城': '广州',
|
|
|
|
|
'tianhe': '广州',
|
|
|
|
|
'yuexiu': '广州',
|
|
|
|
|
'haizhu': '广州',
|
|
|
|
|
'liwan': '广州',
|
|
|
|
|
'baiyun': '广州',
|
|
|
|
|
'huangpu': '广州',
|
|
|
|
|
'panyu': '广州',
|
|
|
|
|
'huadu': '广州',
|
|
|
|
|
'nansha': '广州',
|
|
|
|
|
'conghua': '广州',
|
|
|
|
|
'zengcheng': '广州'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# 检查是否是区级单位,如果是则映射到市级城市
|
|
|
|
|
city_lower = city_name.lower()
|
|
|
|
|
if city_lower in district_to_city_map:
|
|
|
|
|
mapped_city = district_to_city_map[city_lower]
|
|
|
|
|
print(f"智能映射: {city_name} -> {mapped_city}")
|
|
|
|
|
city_name = mapped_city
|
|
|
|
|
|
|
|
|
|
if city_name in self.city_id_map:
|
|
|
|
|
# 如果是英文城市名,先映射到中文
|
|
|
|
|
mapped_name = self.city_id_map.get(city_name)
|
|
|
|
|
|