diff --git a/app.py b/app.py index 117aeba..1ca604f 100644 --- a/app.py +++ b/app.py @@ -806,6 +806,180 @@ Sitemap: {}sitemap.xml response.headers['Content-Type'] = 'text/plain; charset=utf-8' return response + # ========== SEO工具管理路由 (v2.4新增) ========== + @app.route('/admin/seo-tools') + @login_required + def seo_tools(): + """SEO工具管理页面""" + # 检查static/sitemap.xml是否存在及最后更新时间 + sitemap_path = 'static/sitemap.xml' + sitemap_info = None + if os.path.exists(sitemap_path): + import time + mtime = os.path.getmtime(sitemap_path) + sitemap_info = { + 'exists': True, + 'last_updated': datetime.fromtimestamp(mtime).strftime('%Y-%m-%d %H:%M:%S'), + 'size': os.path.getsize(sitemap_path) + } + else: + sitemap_info = {'exists': False} + + return render_template('admin/seo_tools.html', sitemap_info=sitemap_info) + + @app.route('/api/generate-static-sitemap', methods=['POST']) + @login_required + def generate_static_sitemap(): + """生成静态sitemap.xml文件""" + try: + # 获取所有启用的网站 + sites = Site.query.filter_by(is_active=True).order_by(Site.updated_at.desc()).all() + + # 获取所有标签 + tags = Tag.query.all() + + # 构建XML内容(使用网站配置的域名) + base_url = request.url_root.rstrip('/') + + xml_content = ''' +''' + + # 首页 + xml_content += f''' + + {base_url} + daily + 1.0 + ''' + + # 工具详情页 + for site in sites: + xml_content += f''' + + {base_url}/site/{site.code} + {site.updated_at.strftime('%Y-%m-%d') if site.updated_at else datetime.now().strftime('%Y-%m-%d')} + weekly + 0.8 + ''' + + # 标签页 + for tag in tags: + xml_content += f''' + + {base_url}/?tag={tag.slug} + weekly + 0.6 + ''' + + xml_content += ''' +''' + + # 保存到static目录 + static_dir = 'static' + os.makedirs(static_dir, exist_ok=True) + sitemap_path = os.path.join(static_dir, 'sitemap.xml') + + with open(sitemap_path, 'w', encoding='utf-8') as f: + f.write(xml_content) + + # 统计信息 + total_urls = 1 + len(sites) + len(tags) # 首页 + 工具页 + 标签页 + + return jsonify({ + 'success': True, + 'message': f'静态sitemap.xml生成成功!共包含 {total_urls} 个URL', + 'total_urls': total_urls, + 'file_path': sitemap_path, + 'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S') + }) + + except Exception as e: + return jsonify({ + 'success': False, + 'message': f'生成失败: {str(e)}' + }), 500 + + @app.route('/api/notify-search-engines', methods=['POST']) + @login_required + def notify_search_engines(): + """通知搜索引擎sitemap更新""" + try: + import requests + from urllib.parse import quote + + # 获取sitemap URL(使用当前请求的域名) + sitemap_url = request.url_root.rstrip('/') + '/sitemap.xml' + encoded_sitemap_url = quote(sitemap_url, safe='') + + results = [] + + # 1. 通知Google + google_ping_url = f'http://www.google.com/ping?sitemap={encoded_sitemap_url}' + try: + google_response = requests.get(google_ping_url, timeout=10) + results.append({ + 'engine': 'Google', + 'status': 'success' if google_response.status_code == 200 else 'failed', + 'status_code': google_response.status_code, + 'message': '提交成功' if google_response.status_code == 200 else f'HTTP {google_response.status_code}' + }) + except Exception as e: + results.append({ + 'engine': 'Google', + 'status': 'error', + 'message': f'请求失败: {str(e)}' + }) + + # 2. 通知Baidu + baidu_ping_url = f'http://data.zz.baidu.com/ping?sitemap={encoded_sitemap_url}' + try: + baidu_response = requests.get(baidu_ping_url, timeout=10) + results.append({ + 'engine': 'Baidu', + 'status': 'success' if baidu_response.status_code == 200 else 'failed', + 'status_code': baidu_response.status_code, + 'message': '提交成功' if baidu_response.status_code == 200 else f'HTTP {baidu_response.status_code}' + }) + except Exception as e: + results.append({ + 'engine': 'Baidu', + 'status': 'error', + 'message': f'请求失败: {str(e)}' + }) + + # 3. 通知Bing + bing_ping_url = f'http://www.bing.com/ping?sitemap={encoded_sitemap_url}' + try: + bing_response = requests.get(bing_ping_url, timeout=10) + results.append({ + 'engine': 'Bing', + 'status': 'success' if bing_response.status_code == 200 else 'failed', + 'status_code': bing_response.status_code, + 'message': '提交成功' if bing_response.status_code == 200 else f'HTTP {bing_response.status_code}' + }) + except Exception as e: + results.append({ + 'engine': 'Bing', + 'status': 'error', + 'message': f'请求失败: {str(e)}' + }) + + # 统计成功数量 + success_count = sum(1 for r in results if r['status'] == 'success') + + return jsonify({ + 'success': True, + 'message': f'已通知 {success_count}/{len(results)} 个搜索引擎', + 'sitemap_url': sitemap_url, + 'results': results + }) + + except Exception as e: + return jsonify({ + 'success': False, + 'message': f'通知失败: {str(e)}' + }), 500 + @app.route('/api/refresh-site-news/', methods=['POST']) def refresh_site_news(site_code): """手动刷新指定网站的新闻(前台用户可访问)- v2.3新增""" diff --git a/templates/admin/master.html b/templates/admin/master.html index 66c5a87..9f0c081 100644 --- a/templates/admin/master.html +++ b/templates/admin/master.html @@ -79,6 +79,12 @@