liumiaomiao преди 1 ден
родител
ревизия
dc3c2d1e7e
променени са 33 файла, в които са добавени 3798 реда и са изтрити 140 реда
  1. 58 6
      tools/test.py
  2. 5 5
      tools/从es导出数据/es.py
  3. 17 17
      tools/从mongo库导出数据execl/mongo_to_execl.py
  4. BIN
      tools/从mongo库导出数据execl/output.xlsx
  5. 8 9
      tools/数据抽样/sample_data_export_new.py
  6. 5 5
      tools/数据抽样/抽样方法最新.py
  7. BIN
      tools/数据质量监控平台/kb-数据问题统计/KB问题统计汇总.xlsx
  8. 2 2
      tools/数据质量监控平台/kb-数据问题统计/execl_kb.py
  9. 9 2
      tools/数据质量监控平台/kb-数据问题统计/task_kb.py
  10. 291 0
      tools/数据质量监控平台/kb-数据问题统计/统计kb工单中所有的客户问题分类.py
  11. 266 0
      tools/数据质量监控平台/拟在建基础信息分析结果入库_联通.py
  12. 268 0
      tools/数据质量监控平台/新闻基础信息分析结果入库_联通.py
  13. 335 0
      tools/数据质量监控平台/标讯基础信息分析结果入库_联通.py
  14. 269 0
      tools/数据质量监控平台/预算基础信息分析结果入库_联通.py
  15. 53 8
      tools/标准样本数据入库/execl_into_mongo.py
  16. BIN
      tools/生成标准样本库的分析数据/数据分析结果.xlsx
  17. 24 15
      tools/生成标准样本库的分析数据/根据样本数据拉取正式数据生成分析表mongo.py
  18. 196 47
      tools/生成标准样本库的分析数据/生成统计结果.py
  19. 19 17
      tools/生成标准样本库的分析数据/生成统计结果_入库.py
  20. 21 7
      tools/联通项目/data_timeliness.py
  21. 152 0
      tools/联通项目/data_timeliness_bak.py
  22. 940 0
      tools/联通项目/sites_data.csv
  23. BIN
      tools/联通项目/字段缺失率/.~字段缺失率基础数据.xlsx
  24. 165 0
      tools/联通项目/字段缺失率/基础数据入库.py
  25. BIN
      tools/联通项目/字段缺失率/字段缺失率基础数据.xlsx
  26. BIN
      tools/联通项目/数据时效统计表.xlsx
  27. BIN
      tools/联通项目/新闻类覆盖率/news_site_liantong.xlsx
  28. BIN
      tools/联通项目/新闻类覆盖率/news_site_liantong_area.xlsx
  29. 6 0
      tools/联通项目/新闻类覆盖率/test.py
  30. 109 0
      tools/联通项目/新闻类覆盖率/判断站点是否有效.py
  31. 57 0
      tools/联通项目/新闻类覆盖率/寻找原始网站.py
  32. 369 0
      tools/联通项目/新闻类覆盖率/寻找原始网站_v1.py
  33. 154 0
      tools/联通项目/覆盖率原始站点入库.py

+ 58 - 6
tools/test.py

@@ -1,8 +1,60 @@
-from datetime import datetime, timedelta
+import pandas as pd
+from pymongo import MongoClient
+from bson import ObjectId, json_util
+import json
 
-# 定义一周的时间范围,转换为Unix时间戳格式
-end_date = datetime(2025, 7, 10, 12, 0, 0)  # 需要创建datetime对象
-start_date = int((end_date - timedelta(days=7)).timestamp())
-end_timestamp = int(end_date.timestamp())
+# 连接到 MongoDB
+client = MongoClient('172.20.45.129', 27002)
+db = client['data_quality']
+collection = db['standard_sample_data']
 
-print(f"开始时间:{start_date} -- 结束时间:{end_timestamp}")
+
+def insert_without_escape(collection, record):
+    """插入数据并确保引号不被转义"""
+    try:
+        # 1. 将 ObjectId 转为字符串(临时解决序列化问题)
+        if '_id' in record and isinstance(record['_id'], ObjectId):
+            record['_id'] = str(record['_id'])
+
+        # 2. 手动处理引号(确保不被转义)
+        if 'projectname' in record:
+            record['projectname'] = record['projectname'].replace('\\"', '"')
+
+        # 3. 使用 json_util 处理特殊类型
+        record_json = json_util.dumps(record)
+        record_for_db = json_util.loads(record_json)
+
+        # 4. 还原 ObjectId
+        if '_id' in record_for_db and isinstance(record['_id'], str):
+            record_for_db['_id'] = ObjectId(record['_id'])
+
+        # 5. 插入数据
+        collection.replace_one(
+            {"_id": record_for_db.get("_id", ObjectId())},
+            record_for_db,
+            upsert=True
+        )
+        return True
+    except Exception as e:
+        print(f"插入失败: {str(e)}")
+        return False
+
+
+# 示例记录
+record = {
+    "_id": ObjectId("6864eb6dd5d8e4081f7a6a79"),
+    "projectname": '中职学校"物理、化学、生物探索实践工坊"实训室改造项目',
+    "site": "甘肃省阳光招标采购平台",
+    "budget": 138295.32
+}
+
+# 插入数据
+if insert_without_escape(collection, record):
+    print("✅ 插入成功")
+
+    # 验证存储结果"_id": object_id
+    doc = collection.find_one({"_id": ObjectId(record["_id"])})
+    print("MongoDB 实际存储内容:")
+    print(doc["projectname"])  # 应输出:中职学校"物理、化学、生物探索实践工坊"实训室改造项目
+else:
+    print("❌ 插入失败")

+ 5 - 5
tools/从es导出数据/es.py

@@ -21,7 +21,7 @@ def ES_bidding(es_query):
         'mg_host': '172.20.45.129',
         'mg_port': 27002,
         'database': 'data_quality',
-        'collection': 'bidding_20250702'
+        'collection': 'bidding_20250728'
     }
     query = es_query
     # 传入查询语句query 以及配置信息
@@ -29,11 +29,11 @@ def ES_bidding(es_query):
 
 def run():
     # 根据ES语句查找bidding
-    es_query = {"track_total_hits": True,
-                "query": {"bool": {"must": [{"range": {"comeintime": {"from": "1751385600", "to": "1751472000"}}}]}}}
     # es_query = {"track_total_hits": True,
-    #             "query": {"bool": {"must": [{"range": {"publishtime": {"from": "1691337600", "to": "1691424000"}}},
-    #                                         {"terms": {"subtype": ["中标", "合同","成交"]}}]}}}
+    #             "query": {"bool": {"must": [{"range": {"comeintime": {"from": "1753545600", "to": "1753632000"}}}]}}}
+    es_query = {"track_total_hits": True,
+                "query": {"bool": {"must": [{"range": {"publishtime": {"from": "1753545600", "to": "1753632000"}}},
+                                            {"terms": {"toptype": ["拟建", "预告"]}}]}}}
     ES_bidding(es_query)
 
 run()

+ 17 - 17
tools/从mongo库导出数据execl/mongo_to_execl.py

@@ -14,7 +14,7 @@ def export_to_excel(db_name, collection_name, fields, output_file):
     - output_file: 输出的Excel文件名
     """
     # 连接到MongoDB
-    # client = MongoClient('mongodb://172.20.45.129:27002/')
+    # client = MongoClient('172.20.45.129', 27002, unicode_decode_error_handler="ignore")
     client = MongoClient('mongodb://127.0.0.1:27087/', unicode_decode_error_handler="ignore",directConnection=True)  # 修改为你的连接地址
 
     # client = MongoClient('mongodb://127.0.0.1:27087/', unicode_decode_error_handler="ignore",directConnection=True)  # 清洗库
@@ -26,22 +26,22 @@ def export_to_excel(db_name, collection_name, fields, output_file):
     projection = {field: 1 for field in fields}
 
     # 查询数据
-    data = collection.find({"tag": 11},projection).sort("_id", 1)
+    data = collection.find({ "tag_new" : 1 },projection).sort("_id", 1)
 
     # 将数据转换为DataFrame
     df = pd.DataFrame(list(data))
 
-    # # 转换时间戳字段
-    # time_fields = ['bidopentime', 'bidendtime']
-    # for field in time_fields:
-    #     if field in df.columns:
-    #         # 1. 转换为 datetime 对象(秒级时间戳)
-    #         df[field] = pd.to_datetime(df[field], unit='s', errors='coerce')
-    #         # 2. 转换为北京时间(UTC+8)
-    #         beijing_tz = pytz.timezone('Asia/Shanghai')
-    #         df[field] = df[field].dt.tz_localize('UTC').dt.tz_convert(beijing_tz)
-    #         # 3. 去掉时区信息,保留纯时间(否则Excel可能显示异常)
-    #         df[field] = df[field].dt.tz_localize(None)
+    # 转换时间戳字段
+    time_fields = ['bidopentime', 'bidendtime']
+    for field in time_fields:
+        if field in df.columns:
+            # 1. 转换为 datetime 对象(秒级时间戳)
+            df[field] = pd.to_datetime(df[field], unit='s', errors='coerce')
+            # 2. 转换为北京时间(UTC+8)
+            beijing_tz = pytz.timezone('Asia/Shanghai')
+            df[field] = df[field].dt.tz_localize('UTC').dt.tz_convert(beijing_tz)
+            # 3. 去掉时区信息,保留纯时间(否则Excel可能显示异常)
+            df[field] = df[field].dt.tz_localize(None)
 
     # 导出到Excel文件
     df.to_excel(output_file, index=False)
@@ -50,15 +50,15 @@ if __name__ == "__main__":
     # 连接到 MongoDB
 
     db_name = 'jyqyfw'  # 替换为你的数据库名称
-    # db_name = 'jyqyfw'  # 替换为你的数据库名称
     # collection_name = 'standard_sample_data_all_ai' # 替换为你的集合名称
     # collection_name = 'xzh_20250714'  # 替换为你的集合名称
-    collection_name = 'xzh_20250714_1'  # 替换为你的集合名称
+    collection_name = 'usermail_Unicom_0714_1'  # 替换为你的集合名称
     # 定义参数
 
-    # fields = ['_id','id','site','toptype','subtype','area','city','buyer','projectname','projectcode','budget','s_winner','bidamount','label','href','jybxhref','package']  # 替换为你需要导出的字段
+    fields = ['_id','id','site','toptype','subtype','area','city','buyer','projectname','projectcode','budget','s_winner','bidamount','label','href','jybxhref','package','bidopentime', 'bidendtime','pkg_tag']  # 替换为你需要导出的字段
     # fields = ['id','site','toptype','subtype','area','city','buyer','projectname','projectcode','budget','s_winner','bidamount','label','href','jybxhref']  # 替换为你需要导出的字段
-    fields = ['id','title','projectname','href','projectcode','subtype','s_winner','bidamount','buyer']  # 替换为你需要导出的字段
+    # fields = ['id','title','projectname','href','projectcode','subtype','s_winner','bidamount','buyer']  # 替换为你需要导出的字段
+    # fields = ['id','toptype','subtype','title','owner','total_investment','project_startdate','project_completedate','construction_area','floor_area','projectaddr','project_scale','approval_date','note','href','jytest_href']  # 替换为你需要导出的字段
     output_file = 'output.xlsx'
 
     # 调用函数导出数据

BIN
tools/从mongo库导出数据execl/output.xlsx


+ 8 - 9
tools/数据抽样/sample_data_export_new.py

@@ -1,15 +1,14 @@
 from pymongo import MongoClient
 def sample_data(N):
-    db = MongoClient('172.20.45.129', 27002, unicode_decode_error_handler="ignore").data_quality
-    # db = MongoClient('mongodb://127.0.0.1:27087/', unicode_decode_error_handler="ignore",directConnection=True).jyqyfw  # 清洗库
+    # db = MongoClient('172.20.45.129', 27002, unicode_decode_error_handler="ignore").data_quality
+    db = MongoClient('mongodb://127.0.0.1:27087/', unicode_decode_error_handler="ignore",directConnection=True).jyqyfw  # 清洗库
+    coll_user = db["usermail_Unicom_0714_1"]
 
-    coll_user = db["missing_fid_attachments"]
-
-    # filter_condition = {"tag_1": 1}
+    filter_condition = {"clear_tag" : None }
     # 获取所有站点及其文档数
     site_list = {}
     site_count = coll_user.aggregate([
-        # {"$match": filter_condition},
+        {"$match": filter_condition},
         {"$group": {"_id": "$site", "count": {"$sum": 1}}},
         {"$sort": {"count": -1}}
     ])
@@ -35,7 +34,7 @@ def sample_data(N):
         pipeline = [
             {"$match": {
                     "site": site,
-                    # **filter_condition
+                    **filter_condition
                     }
              },
             {"$match": {"site": site}},
@@ -49,10 +48,10 @@ def sample_data(N):
 
         update_result = coll_user.update_many(
             {"_id": {"$in": sampled_ids}},
-            {"$set": {"flag": 1}}
+            {"$set": {"tag_new": 1}}
         )
         marked_count += update_result.modified_count
         remaining -= update_result.modified_count
 
     print(f"Total marked documents: {marked_count}")
-sample_data(8000)
+sample_data(200)

+ 5 - 5
tools/数据抽样/抽样方法最新.py

@@ -11,15 +11,15 @@ def sample_data(N):
     """
     # 连接MongoDB
     client = MongoClient(
-        'mongodb://127.0.0.1:27017/',
+        'mongodb://127.0.0.1:27087/',
         unicode_decode_error_handler="ignore",
         directConnection=True
     )
     db = client.jyqyfw  # 数据库名
-    coll_user = db["usermail_Unicom_1_2"]  # 集合名
+    coll_user = db["xzh_20250714"]  # 集合名
 
-    # 查询条件:只处理tag=1或2的文档
-    filter_condition = {"$or": [{"tag": 1}, {"tag": 2}]}
+    # 查询条件
+    filter_condition = { "clear_tag" : None}
 
     print(f"开始抽样,目标样本量: {N}")
 
@@ -105,4 +105,4 @@ def sample_data(N):
 
 
 # 示例:抽取2000条文档
-sample_data(2000)
+sample_data(300)

BIN
tools/数据质量监控平台/kb-数据问题统计/KB问题统计汇总.xlsx


+ 2 - 2
tools/数据质量监控平台/kb-数据问题统计/execl_kb.py

@@ -13,7 +13,7 @@ db_connection_remote = pymysql.connect(
 
 # 读取Excel文件
 file_path = "KB问题统计汇总.xlsx"  # 请替换为实际的文件路径
-df = pd.read_excel(file_path, sheet_name="kB问题数据源")  # 读取指定的sheet页
+df = pd.read_excel(file_path, sheet_name="6月")  # 读取指定的sheet页
 
 # 选取需要的列
 df = df[['年份', '月份', '描述', '站点', '链接', '爬虫', '备注','问题分类一级','问题分类二级']]  # 根据实际列名调整
@@ -29,7 +29,7 @@ with db_connection_remote.cursor() as cursor:
     for _, row in df.iterrows():
         # 插入数据的SQL语句
         sql = """
-        INSERT INTO problem_analysis (year, month, problem_description, site, link, spider, notes,category_level_1,category_level_2)
+        INSERT INTO kb_analysis (year, month, problem_description, site, link, spider, notes,category_level_1,category_level_2)
         VALUES (%s, %s, %s, %s, %s, %s, %s,%s,%s)
         """
         values = (

+ 9 - 2
tools/数据质量监控平台/kb-数据问题统计/task_kb.py

@@ -32,12 +32,19 @@ def test_connection():
     try:
         print("开始连接本地数据库...")
         db_connection_local = pymysql.connect(
-            host="127.0.0.1",
+            host="172.31.31.204",
             user="kanboard",
             password="K99b3e9qa9d",
             database="kanboard",
-            port=4001
+            port=3366
         )
+        # db_connection_local = pymysql.connect(
+        #     host="127.0.0.1",
+        #     user="kanboard",
+        #     password="K99b3e9qa9d",
+        #     database="kanboard",
+        #     port=4001
+        # )
         cursor_local = db_connection_local.cursor()
 
         print("开始连接远程数据库...")

+ 291 - 0
tools/数据质量监控平台/kb-数据问题统计/统计kb工单中所有的客户问题分类.py

@@ -0,0 +1,291 @@
+import pymysql
+from pymysql import MySQLError
+from datetime import datetime, timedelta
+
+
+def get_last_week_monday_friday():
+    """获取上周一和上周五的 Unix 时间戳"""
+    today = datetime.utcnow()
+    last_monday = today - timedelta(days=today.weekday() + 7)  # 上周一
+    last_friday = last_monday + timedelta(days=4)  # 上周五
+
+    last_monday_timestamp = int(last_monday.replace(hour=0, minute=0, second=0).timestamp())
+    last_friday_timestamp = int(last_friday.replace(hour=23, minute=59, second=59).timestamp())
+
+    return last_monday_timestamp, last_friday_timestamp
+
+def get_last_month_first_last_day():
+    """获取上个月第一天和最后一天的 Unix 时间戳"""
+    # 获取当前时间
+    today = datetime.utcnow()
+
+    # 计算上个月的第一天
+    first_day_of_last_month = today.replace(day=1) - timedelta(days=1)  # 先跳到上个月最后一天
+    first_day_of_last_month = first_day_of_last_month.replace(day=1)  # 再设置为上个月第一天
+
+    # 计算上个月的最后一天
+    last_day_of_last_month = today.replace(day=1) - timedelta(days=1)  # 上个月最后一天
+
+    # 转换为 Unix 时间戳(第一天 00:00:00,最后一天 23:59:59)
+    first_day_timestamp = int(first_day_of_last_month.replace(hour=0, minute=0, second=0).timestamp())
+    last_day_timestamp = int(last_day_of_last_month.replace(hour=23, minute=59, second=59).timestamp())
+
+    return first_day_timestamp, last_day_timestamp
+
+def close_connection(cursor, connection):
+    """确保数据库连接被关闭"""
+    if cursor:
+        cursor.close()
+    if connection:
+        connection.close()
+
+def classify_issue(title, tags):
+    title = title.lower()  # 转换为小写,避免大小写影响匹配
+    tags = [tag.lower() for tag in tags]  # 标签也转换为小写
+
+    # 1. 检查"数据补录"
+    if ("补录" in title or "数据补录" in title or "采集" in title) and any("补录" in tag or "数据补录" in tag for tag in tags):
+        return "数据补录"
+
+    # 2. 检查"权益问题"
+    if  any(keyword in title for keyword in ["权益", "权限", "变更", "更改"]):
+        return "权益问题"
+
+    # 3. 检查"数据错误"
+    if ("抽错" in title ) or any(keyword in tag for tag in tags for keyword in ["错误", "项目名称问题"]):
+        return "数据错误"
+
+    # 4. 检查"漏推"
+    if any(keyword in title for keyword in ["漏采", "遗漏", "漏推", "未采集"]):
+        return "漏推"
+
+    # 5. 检查"数据缺失"
+    if any("数据缺失" in tag for tag in tags):
+        return "数据缺失"
+    # 6. 检查"数据重复"
+    if "重复" in title :
+        return "数据重复"
+    # 7. 检查"数据修改"
+    if any("数据修改" in tag for tag in tags):
+        return "数据修改"
+    # 8. 检查"附件问题"
+    if any("附件问题" in tag for tag in tags):
+        return "附件问题"
+
+    # 9. 检查"新需求"
+    if any("评审" in tag for tag in tags) or any("转交功能研发" in tag for tag in tags):
+        return "新需求"
+    # 10. 检查"问题排查"
+    if any("问题排查" in tag for tag in tags):
+        return "问题排查"
+    # 11. 检查"无问题"
+    if any("无问题" in tag for tag in tags):
+        return "无问题"
+    # 12. 默认返回"其它"
+    return "其它"
+def test_connection():
+    cursor_local = None
+    cursor_remote = None
+    db_connection_local = None
+    db_connection_remote = None
+
+    try:
+        print("开始连接本地数据库...")
+        db_connection_local = pymysql.connect(
+            host="172.31.31.204",
+            user="kanboard",
+            password="K99b3e9qa9d",
+            database="kanboard",
+            port=3366
+        )
+        # db_connection_local = pymysql.connect(
+        #     host="127.0.0.1",
+        #     user="kanboard",
+        #     password="K99b3e9qa9d",
+        #     database="kanboard",
+        #     port=4001
+        # )
+        cursor_local = db_connection_local.cursor()
+
+        print("开始连接远程数据库...")
+        db_connection_remote = pymysql.connect(
+            host="172.20.45.129",
+            user="root",
+            password="=PDT49#80Z!RVv52_z",
+            database="quality",
+            port=4000
+        )
+        cursor_remote = db_connection_remote.cursor()
+
+        start_timestamp, end_timestamp = get_last_month_first_last_day()
+        # start_timestamp = 1748707200
+        # end_timestamp = 1751299200
+        print(
+            f"查询时间范围: {datetime.utcfromtimestamp(start_timestamp)} - {datetime.utcfromtimestamp(end_timestamp)}")
+
+        print("开始执行查询...")
+        query = """
+        SELECT t.id AS task_id, 
+               t.date_started, 
+               t.date_moved, 
+               t.external_uri, 
+               t.title,          
+               t.owner_id, 
+               t.creator_id, 
+               t.column_id
+        FROM tasks t
+        JOIN task_has_tags tht ON t.id = tht.task_id
+        JOIN tags tg ON tht.tag_id = tg.id
+        WHERE t.project_id = 261
+          AND t.date_started >= %s
+          AND t.date_started <= %s
+          AND tg.project_id = 261
+        """
+        cursor_local.execute(query, (start_timestamp, end_timestamp))
+        results = cursor_local.fetchall()
+        if not results:
+            print("没有找到符合条件的数据")
+            return
+
+        print(f"查询到 {len(results)} 条数据")
+
+        # 获取当前日期
+        current_date = datetime.utcnow().strftime('%Y-%m-%d')  # 当前日期格式:YYYY-MM-DD
+        now = datetime.utcnow()
+        # 正确计算上个月的年份和月份
+        if now.month == 1:
+            # 如果是1月,上个月是去年的12月
+            year = now.year - 1
+            month = 12
+        else:
+            # 其他月份直接减1
+            year = now.year
+            month = now.month - 1
+
+        # 初始化分类统计字典 - 确保包含所有可能的字段
+        category_stats = {
+            'data_replenish': 0,  # 数据补录
+            'rights_issue': 0,  # 权益问题
+            'data_error': 0,  # 数据错误
+            'missed_push': 0,  # 漏推
+            'data_missing': 0,  # 数据缺失
+            'data_duplicate': 0,  # 数据重复
+            'data_modify': 0,  # 数据修改
+            'attachment_issue': 0,  # 附件问题
+            'new_requirement': 0,  # 新需求
+            'problem_investigation': 0,  # 问题排查
+            'no_problem': 0,  # 无问题
+            'other': 0  # 其它
+        }
+        # 分类名称映射(将分类结果映射到字段名)
+        category_mapping = {
+            '数据补录': 'data_replenish',
+            '权益问题': 'rights_issue',
+            '数据错误': 'data_error',
+            '漏推': 'missed_push',
+            '数据缺失': 'data_missing',
+            '数据重复': 'data_duplicate',
+            '数据修改': 'data_modify',
+            '附件问题': 'attachment_issue',
+            '新需求': 'new_requirement',
+            '问题排查': 'problem_investigation',
+            '无问题': 'no_problem',
+            '其它': 'other'
+        }
+        print("开始处理数据...")
+        for task in results:
+            task_id, date_started, date_moved, external_uri, title, owner_id, creator_id, column_id = task
+
+            # 获取任务对应的所有标签名称
+            cursor_local.execute(""" 
+                SELECT tg.name 
+                FROM task_has_tags tht 
+                JOIN tags tg ON tht.tag_id = tg.id 
+                WHERE tht.task_id = %s AND tg.project_id = 261 
+            """, (task_id,))
+            tags = cursor_local.fetchall()
+            tags_list = [tag[0] for tag in tags]  # 获取所有标签名称
+
+            customer_category=classify_issue(title,tags_list)
+            # 更新分类统计
+            # 更新对应字段的统计
+            if customer_category in category_mapping:
+                field_name = category_mapping[customer_category]
+                category_stats[field_name] += 1
+            else:
+                category_stats['other'] += 1
+            # 计算总数和占比
+        total_count = len(results)
+        print(f"\n分类统计结果:")
+        for category, count in category_stats.items():
+                proportion = round((count / total_count) * 100, 2) if total_count > 0 else 0
+                print(f"{category}: {count} 条 ({proportion}%)")
+
+        # 插入数据到新结构的表
+        cursor_remote.execute("""
+            INSERT INTO kb_customer_classification (
+                stats_date,
+                data_replenish,
+                rights_issue,
+                data_error,
+                missed_push,
+                data_missing,
+                data_duplicate,
+                data_modify,
+                attachment_issue,
+                new_requirement,
+                problem_investigation,
+                no_problem,
+                other,
+                create_time,
+                year,
+                month
+            ) VALUES (
+                %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s
+            )
+            ON DUPLICATE KEY UPDATE
+                data_replenish = VALUES(data_replenish),
+                rights_issue = VALUES(rights_issue),
+                data_error = VALUES(data_error),
+                missed_push = VALUES(missed_push),
+                data_missing = VALUES(data_missing),
+                data_duplicate = VALUES(data_duplicate),
+                data_modify = VALUES(data_modify),
+                attachment_issue = VALUES(attachment_issue),
+                new_requirement = VALUES(new_requirement),
+                problem_investigation = VALUES(problem_investigation),
+                no_problem = VALUES(no_problem),
+                other = VALUES(other),
+                update_time = CURRENT_TIMESTAMP
+        """, (
+            current_date,
+            category_stats['data_replenish'],
+            category_stats['rights_issue'],
+            category_stats['data_error'],
+            category_stats['missed_push'],
+            category_stats['data_missing'],
+            category_stats['data_duplicate'],
+            category_stats['data_modify'],
+            category_stats['attachment_issue'],
+            category_stats['new_requirement'],
+            category_stats['problem_investigation'],
+            category_stats['no_problem'],
+            category_stats['other'],
+            current_date,
+            year,
+            month
+        ))
+
+        db_connection_remote.commit()
+        print("数据处理完成!")
+
+    except MySQLError as e:
+        print(f"发生错误: {e}")
+
+    finally:
+        close_connection(cursor_local, db_connection_local)
+        close_connection(cursor_remote, db_connection_remote)
+
+
+if __name__ == "__main__":
+    test_connection()

+ 266 - 0
tools/数据质量监控平台/拟在建基础信息分析结果入库_联通.py

@@ -0,0 +1,266 @@
+from datetime import date, timedelta,datetime
+import pandas as pd
+import pymysql
+from sqlalchemy import create_engine
+import json
+
+# MySQL 连接配置
+mysql_config = {
+    "host": "172.20.45.129",
+    "port": 4000,
+    "user": "root",
+    "password": "=PDT49#80Z!RVv52_z",
+    "database": "quality"
+}
+
+# SQLAlchemy 连接字符串
+engine = create_engine(
+    f'mysql+pymysql://{mysql_config["user"]}:{mysql_config["password"]}@{mysql_config["host"]}:{mysql_config["port"]}/{mysql_config["database"]}')
+
+def get_this_week_thursday():
+    today = date.today()
+    delta = (3 - today.weekday()) % 7  # 计算到本周四的天数差(兼容跨周)
+    return today + timedelta(days=delta)
+
+# 动态获取本周四的日期
+# query_create_time = get_this_week_thursday().strftime("%Y-%m-%d")  # ✅ 动态获取
+# query_create_time = '2025-04-02'
+now_date = (datetime.now()).strftime("%Y-%m-%d")
+# yesterday_date = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
+batch_id = now_date
+# batch_id = '2025-07-28'
+print(batch_id)
+
+
+# 从 MySQL 获取数据
+def fetch_data_from_mysql(query, params=None):
+    # 确保参数是元组格式
+    if params is not None and isinstance(params, list):
+        params = tuple(params)
+    df = pd.read_sql(query, engine, params=params)
+    return df
+
+
+
+# SQL 查询条件
+query = f"SELECT * FROM nzj_analysis_liantong  WHERE create_time = '{batch_id}'"
+data = fetch_data_from_mysql(query)
+print(data.columns, "第一轮数据检索成功")
+
+# 字段映射
+column_name_mapping = {
+    "area_qa": "省份",
+    "city_qa": "城市",
+    "district_qa":"区县",
+    "projectname_qa": "项目名称",
+    "project_stage_code_qa": "公告阶段",
+    "capital_qa" :"投资金额",
+    "score": "标讯总分数",
+}
+# 只从 error_type 字段提取数据
+def extract_errors(df):
+    # 定义只从 error_type 中映射的字段
+    qa_fields = list(column_name_mapping.values())
+
+    if "error_type" in df.columns:
+        print("✅ 'error_type' 字段存在,开始提取数据")
+
+        # 处理 error_type 字段,如果它是字符串类型,将其转换为字典
+        df['error_type'] = df['error_type'].apply(lambda x: json.loads(x) if isinstance(x, str) else x)
+
+        # 打印 error_type 字段的前几行,确认其数据类型
+        print("error_type 字段数据示例:")
+        print(df['error_type'].head())
+
+        for qa_field in qa_fields:
+            english_field = next((k for k, v in column_name_mapping.items() if v == qa_field), None)
+            if english_field:
+                print(f"正在提取字段: {qa_field}, 对应的英文字段: {english_field}")
+                # 打印出提取过程中的一些信息
+                df[qa_field] = df['error_type'].apply(
+                    lambda x: x.get(english_field) if isinstance(x, dict) and x.get(english_field) != {} else None
+                )
+
+        # 提取标讯总分数
+        df['标讯总分数'] = df['error_type'].apply(lambda x: x.get("score") if isinstance(x, dict) else None)
+        df['标讯总分数'] = pd.to_numeric(df['标讯总分数'], errors='coerce')  # 转换为数值类型
+
+    print(f"✅ 提取后的数据:{df.head()}")
+    return df
+
+
+# 提取数据
+data = extract_errors(data)
+
+# 检查提取后的数据
+print("提取后的数据:")
+print(data.head())  # 打印前几行数据进行检查
+
+# 检查 error_type 的类型分布
+print("error_type 字段的类型分布:")
+print(data['error_type'].apply(type).value_counts())
+
+data_bid = data.copy()  # 招标数据
+
+# 打印筛选后的数据行数
+print("筛选后的拟在建数据行数:", len(data_bid))
+
+
+# 数据分析函数
+def analyze_column(dataframe, column_name, data_type, batch_id):
+    if column_name not in dataframe.columns:
+        return None
+
+    total = len(dataframe[column_name])
+    correct = dataframe[column_name].isna().sum()
+    error = total - correct
+
+    # accuracy and error rate with percentage symbol
+    accuracy = f'{(correct / total * 100):.2f}%' if total > 0 else "0%"
+    error_rate = f'{(error / total * 100):.2f}%' if total > 0 else "0%"
+
+    # calculate error rate for individual error reasons, rounded to two decimal places
+    error_code_counts = {}
+    not_exist_counts = 0  # 新增:统计以"不存在!"结尾的错误数量
+    not_exist_rate_percent=0
+
+    for item in dataframe[column_name].dropna():
+        if isinstance(item, dict):
+            for error_code, error_desc in item.items():
+                error_code_counts.setdefault(error_code, {'description': error_desc, 'count': 0})['count'] += 1
+
+    result = []
+    for error_code, data in error_code_counts.items():
+        if error_code == '0000':
+            not_exist_counts = data['count']
+            not_exist_rate_percent = ( not_exist_counts / total) * 100 if total > 0 else 0
+            not_exist_rate_percent = f'{not_exist_rate_percent:.2f}%'
+        # calculate the error rate for the individual reason
+        single_error_rate = (data['count'] / error) * 100 if error > 0 else 0
+        single_error_rate_percent = f'{single_error_rate:.2f}%'  # single reason error rate with percentage
+        error_description=data['description']
+        # 安全查询
+        query = "SELECT error_one, error_two FROM error_dict WHERE error = %s"
+        error_df = fetch_data_from_mysql(query, params=(error_description,))
+
+        # 处理查询结果
+        error_one = error_two = None
+        if not error_df.empty:
+            error_one = error_df.iloc[0]['error_one']
+            error_two = error_df.iloc[0]['error_two']
+        result.append({
+            'record_type': '字段分析',  # 'record_type' -> record_type
+            'field_name': column_name,  # 'field_name' -> field_name
+            'data_type': data_type,  # 'data_type' -> data_type
+            'batch_id': batch_id,  # 'batch_id' -> batch_id
+            'total_count': total,  # 'total_count' -> total_count
+            'correct_count': correct,  # 'correct_count' -> correct_count
+            'error_count': error,  # 'error_count' -> error_count
+            'accuracy': accuracy,  # 'accuracy' -> accuracy
+            'error_rate': error_rate,  # 'error_rate' -> error_rate
+            'error_code': error_code,  # 'error_code' -> error_code
+            'error_description': data['description'],  # 'error_description' -> error_description
+            'field_count': data['count'],  # 'field_count' -> field_count
+            'single_error_rate': single_error_rate_percent,  # 'single_error_rate' -> single_error_rate
+            'error_one':error_one,
+            'error_two':error_two,
+            "not_exist_counts":not_exist_counts,
+            "not_exist_rate_percent":not_exist_rate_percent,
+            "data_source": 2
+        })
+    return result if result else None
+
+# 分析招标和中标数据
+def analyze_data(df, selected_fields, data_type,batch_id):
+    results = []
+    for field in selected_fields:
+        analysis_result = analyze_column(df, field, data_type, batch_id)
+        if analysis_result:
+            results.extend(analysis_result)
+    return pd.DataFrame(results)
+
+
+# 定义需要分析的字段
+
+bid_selected_fields = ["省份", "城市","区县", "项目名称", "业主单位","投资金额","公告阶段"]
+
+# 分析结果
+bid_analysis_df = analyze_data(data_bid, bid_selected_fields, "拟在建",batch_id)
+
+
+# 查看分析结果
+print("拟在建数据分析结果:", bid_analysis_df.head())
+
+
+
+# 分数分析
+def analyze_scores(df):
+    if '标讯总分数' not in df.columns:
+        return []
+
+    total_count = len(df['标讯总分数'])
+    score_counts = df['标讯总分数'].value_counts().sort_index()
+    score_percentage = (score_counts / total_count * 100).round(2).astype(str) + '%'
+
+    score_analysis = []
+    for score, count in score_counts.items():
+        score_analysis.append({
+            "record_type": "分数分析",
+            "score": str(score),
+            "count": int(count),
+            "total": total_count,
+            "percentage": score_percentage[score],
+            "batch_id": batch_id,
+            "data_source":2
+        })
+    return score_analysis
+
+
+# 分数分析结果
+score_analysis_data = analyze_scores(pd.concat([data_bid]))
+print("分数分析结果:", score_analysis_data)
+
+
+# 存储到 MySQL
+def store_analysis_to_mysql(df, table_name):
+    if df.empty:
+        print(f"⚠️ {table_name} 数据为空,跳过存储")
+        return
+
+    connection = pymysql.connect(**mysql_config)
+    cursor = connection.cursor()
+
+    if table_name == "analysis_results_liantong":
+        sql = """
+        INSERT INTO analysis_results_liantong 
+        (record_type, field_name, data_type, batch_id, total_count, correct_count, error_count, accuracy, error_rate, error_code, error_description, field_count, single_error_rate,error_one,error_two,not_exist_counts,not_exist_rate_percent,data_source)
+        VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,%s,%s,%s,%s,%s)
+        """
+
+    elif table_name == "analysis_score_liantong":
+        sql = """
+        INSERT INTO analysis_score_liantong 
+        (record_type, score, count, total, percentage, batch_id,data_source)
+        VALUES (%s, %s, %s, %s, %s, %s,%s)
+        """
+
+    for _, row in df.iterrows():
+        values = tuple(row.fillna("").values)
+
+        if len(values) != sql.count('%s'):
+            print(f"❌ 参数数量不匹配: 预期 {sql.count('%s')},实际 {len(values)},跳过此行")
+            continue
+
+        cursor.execute(sql, values)
+
+    connection.commit()
+    cursor.close()
+    connection.close()
+    print(f"✅ {table_name} 数据已存储到 MySQL")
+
+
+
+store_analysis_to_mysql(bid_analysis_df, "analysis_results_liantong")
+store_analysis_to_mysql(pd.DataFrame(score_analysis_data), "analysis_score_liantong")
+
+print("✅ 分析完成,数据已存入 MySQL!")

+ 268 - 0
tools/数据质量监控平台/新闻基础信息分析结果入库_联通.py

@@ -0,0 +1,268 @@
+from datetime import date, timedelta,datetime
+import pandas as pd
+import pymysql
+from sqlalchemy import create_engine
+import json
+
+# MySQL 连接配置
+mysql_config = {
+    "host": "172.20.45.129",
+    "port": 4000,
+    "user": "root",
+    "password": "=PDT49#80Z!RVv52_z",
+    "database": "quality"
+}
+
+# SQLAlchemy 连接字符串
+engine = create_engine(
+    f'mysql+pymysql://{mysql_config["user"]}:{mysql_config["password"]}@{mysql_config["host"]}:{mysql_config["port"]}/{mysql_config["database"]}')
+
+def get_this_week_thursday():
+    today = date.today()
+    delta = (3 - today.weekday()) % 7  # 计算到本周四的天数差(兼容跨周)
+    return today + timedelta(days=delta)
+
+# 动态获取本周四的日期
+# query_create_time = get_this_week_thursday().strftime("%Y-%m-%d")  # ✅ 动态获取
+# query_create_time = '2025-04-02'
+now_date = (datetime.now()).strftime("%Y-%m-%d")
+# yesterday_date = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
+batch_id = now_date
+# batch_id = '2025-07-28'
+print(batch_id)
+
+
+# 从 MySQL 获取数据
+def fetch_data_from_mysql(query, params=None):
+    # 确保参数是元组格式
+    if params is not None and isinstance(params, list):
+        params = tuple(params)
+    df = pd.read_sql(query, engine, params=params)
+    return df
+
+
+
+# SQL 查询条件
+query = f"SELECT * FROM news_analysis_liantong  WHERE create_time = '{batch_id}'"
+data = fetch_data_from_mysql(query)
+print(data.columns, "第一轮数据检索成功")
+
+# 字段映射
+column_name_mapping = {
+    "area_qa": "省份",
+    "city_qa": "城市",
+    "title_qa":"标题",
+    "publishtime_qa": "发布时间",
+    "publish_org_qa" :"发文单位",
+    "detail_qa" :"正文",
+    "href_qa" :"公告地址",
+    "projectinfo_qa" :"政策附件",
+    "score": "标讯总分数",
+}
+# 只从 error_type 字段提取数据
+def extract_errors(df):
+    # 定义只从 error_type 中映射的字段
+    qa_fields = list(column_name_mapping.values())
+
+    if "error_type" in df.columns:
+        print("✅ 'error_type' 字段存在,开始提取数据")
+
+        # 处理 error_type 字段,如果它是字符串类型,将其转换为字典
+        df['error_type'] = df['error_type'].apply(lambda x: json.loads(x) if isinstance(x, str) else x)
+
+        # 打印 error_type 字段的前几行,确认其数据类型
+        print("error_type 字段数据示例:")
+        print(df['error_type'].head())
+
+        for qa_field in qa_fields:
+            english_field = next((k for k, v in column_name_mapping.items() if v == qa_field), None)
+            if english_field:
+                print(f"正在提取字段: {qa_field}, 对应的英文字段: {english_field}")
+                # 打印出提取过程中的一些信息
+                df[qa_field] = df['error_type'].apply(
+                    lambda x: x.get(english_field) if isinstance(x, dict) and x.get(english_field) != {} else None
+                )
+
+        # 提取标讯总分数
+        df['标讯总分数'] = df['error_type'].apply(lambda x: x.get("score") if isinstance(x, dict) else None)
+        df['标讯总分数'] = pd.to_numeric(df['标讯总分数'], errors='coerce')  # 转换为数值类型
+
+    print(f"✅ 提取后的数据:{df.head()}")
+    return df
+
+
+# 提取数据
+data = extract_errors(data)
+
+# 检查提取后的数据
+print("提取后的数据:")
+print(data.head())  # 打印前几行数据进行检查
+
+# 检查 error_type 的类型分布
+print("error_type 字段的类型分布:")
+print(data['error_type'].apply(type).value_counts())
+
+data_bid = data.copy()  # 招标数据
+
+# 打印筛选后的数据行数
+print("筛选后的拟在建数据行数:", len(data_bid))
+
+
+# 数据分析函数
+def analyze_column(dataframe, column_name, data_type, batch_id):
+    if column_name not in dataframe.columns:
+        return None
+
+    total = len(dataframe[column_name])
+    correct = dataframe[column_name].isna().sum()
+    error = total - correct
+
+    # accuracy and error rate with percentage symbol
+    accuracy = f'{(correct / total * 100):.2f}%' if total > 0 else "0%"
+    error_rate = f'{(error / total * 100):.2f}%' if total > 0 else "0%"
+
+    # calculate error rate for individual error reasons, rounded to two decimal places
+    error_code_counts = {}
+    not_exist_counts = 0  # 新增:统计以"不存在!"结尾的错误数量
+    not_exist_rate_percent=0
+
+    for item in dataframe[column_name].dropna():
+        if isinstance(item, dict):
+            for error_code, error_desc in item.items():
+                error_code_counts.setdefault(error_code, {'description': error_desc, 'count': 0})['count'] += 1
+
+    result = []
+    for error_code, data in error_code_counts.items():
+        if error_code == '0000':
+            not_exist_counts = data['count']
+            not_exist_rate_percent = ( not_exist_counts / total) * 100 if total > 0 else 0
+            not_exist_rate_percent = f'{not_exist_rate_percent:.2f}%'
+        # calculate the error rate for the individual reason
+        single_error_rate = (data['count'] / error) * 100 if error > 0 else 0
+        single_error_rate_percent = f'{single_error_rate:.2f}%'  # single reason error rate with percentage
+        error_description=data['description']
+        # 安全查询
+        query = "SELECT error_one, error_two FROM error_dict WHERE error = %s"
+        error_df = fetch_data_from_mysql(query, params=(error_description,))
+
+        # 处理查询结果
+        error_one = error_two = None
+        if not error_df.empty:
+            error_one = error_df.iloc[0]['error_one']
+            error_two = error_df.iloc[0]['error_two']
+        result.append({
+            'record_type': '字段分析',  # 'record_type' -> record_type
+            'field_name': column_name,  # 'field_name' -> field_name
+            'data_type': data_type,  # 'data_type' -> data_type
+            'batch_id': batch_id,  # 'batch_id' -> batch_id
+            'total_count': total,  # 'total_count' -> total_count
+            'correct_count': correct,  # 'correct_count' -> correct_count
+            'error_count': error,  # 'error_count' -> error_count
+            'accuracy': accuracy,  # 'accuracy' -> accuracy
+            'error_rate': error_rate,  # 'error_rate' -> error_rate
+            'error_code': error_code,  # 'error_code' -> error_code
+            'error_description': data['description'],  # 'error_description' -> error_description
+            'field_count': data['count'],  # 'field_count' -> field_count
+            'single_error_rate': single_error_rate_percent,  # 'single_error_rate' -> single_error_rate
+            'error_one':error_one,
+            'error_two':error_two,
+            "not_exist_counts":not_exist_counts,
+            "not_exist_rate_percent":not_exist_rate_percent,
+            "data_source": 3
+        })
+    return result if result else None
+
+# 分析招标和中标数据
+def analyze_data(df, selected_fields, data_type,batch_id):
+    results = []
+    for field in selected_fields:
+        analysis_result = analyze_column(df, field, data_type, batch_id)
+        if analysis_result:
+            results.extend(analysis_result)
+    return pd.DataFrame(results)
+
+
+# 定义需要分析的字段
+
+bid_selected_fields = ["省份", "城市","发布日期", "发文单位", "标题","正文","公告地址","政策附件"]
+
+# 分析结果
+bid_analysis_df = analyze_data(data_bid, bid_selected_fields, "新闻政策",batch_id)
+
+
+# 查看分析结果
+print("新闻政策数据分析结果:", bid_analysis_df.head())
+
+
+
+# 分数分析
+def analyze_scores(df):
+    if '标讯总分数' not in df.columns:
+        return []
+
+    total_count = len(df['标讯总分数'])
+    score_counts = df['标讯总分数'].value_counts().sort_index()
+    score_percentage = (score_counts / total_count * 100).round(2).astype(str) + '%'
+
+    score_analysis = []
+    for score, count in score_counts.items():
+        score_analysis.append({
+            "record_type": "分数分析",
+            "score": str(score),
+            "count": int(count),
+            "total": total_count,
+            "percentage": score_percentage[score],
+            "batch_id": batch_id,
+            "data_source":3
+        })
+    return score_analysis
+
+
+# 分数分析结果
+score_analysis_data = analyze_scores(pd.concat([data_bid]))
+print("分数分析结果:", score_analysis_data)
+
+
+# 存储到 MySQL
+def store_analysis_to_mysql(df, table_name):
+    if df.empty:
+        print(f"⚠️ {table_name} 数据为空,跳过存储")
+        return
+
+    connection = pymysql.connect(**mysql_config)
+    cursor = connection.cursor()
+
+    if table_name == "analysis_results_liantong":
+        sql = """
+        INSERT INTO analysis_results_liantong 
+        (record_type, field_name, data_type, batch_id, total_count, correct_count, error_count, accuracy, error_rate, error_code, error_description, field_count, single_error_rate,error_one,error_two,not_exist_counts,not_exist_rate_percent,data_source)
+        VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,%s,%s,%s,%s,%s)
+        """
+
+    elif table_name == "analysis_score_liantong":
+        sql = """
+        INSERT INTO analysis_score_liantong 
+        (record_type, score, count, total, percentage, batch_id,data_source)
+        VALUES (%s, %s, %s, %s, %s, %s,%s)
+        """
+
+    for _, row in df.iterrows():
+        values = tuple(row.fillna("").values)
+
+        if len(values) != sql.count('%s'):
+            print(f"❌ 参数数量不匹配: 预期 {sql.count('%s')},实际 {len(values)},跳过此行")
+            continue
+
+        cursor.execute(sql, values)
+
+    connection.commit()
+    cursor.close()
+    connection.close()
+    print(f"✅ {table_name} 数据已存储到 MySQL")
+
+
+
+store_analysis_to_mysql(bid_analysis_df, "analysis_results_liantong")
+store_analysis_to_mysql(pd.DataFrame(score_analysis_data), "analysis_score_liantong")
+
+print("✅ 分析完成,数据已存入 MySQL!")

+ 335 - 0
tools/数据质量监控平台/标讯基础信息分析结果入库_联通.py

@@ -0,0 +1,335 @@
+from datetime import date, timedelta,datetime
+import pandas as pd
+import pymysql
+from sqlalchemy import create_engine
+import json
+
+# MySQL 连接配置
+mysql_config = {
+    "host": "172.20.45.129",
+    "port": 4000,
+    "user": "root",
+    "password": "=PDT49#80Z!RVv52_z",
+    "database": "quality"
+}
+
+# SQLAlchemy 连接字符串
+engine = create_engine(
+    f'mysql+pymysql://{mysql_config["user"]}:{mysql_config["password"]}@{mysql_config["host"]}:{mysql_config["port"]}/{mysql_config["database"]}')
+
+def get_this_week_thursday():
+    today = date.today()
+    delta = (3 - today.weekday()) % 7  # 计算到本周四的天数差(兼容跨周)
+    return today + timedelta(days=delta)
+
+# 动态获取本周四的日期
+# query_create_time = get_this_week_thursday().strftime("%Y-%m-%d")  # ✅ 动态获取
+# query_create_time = '2025-04-02'
+now_date = (datetime.now()).strftime("%Y-%m-%d")
+# yesterday_date = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
+batch_id = now_date
+# batch_id = '2025-07-28'
+print(batch_id)
+
+
+# 从 MySQL 获取数据
+def fetch_data_from_mysql(query, params=None):
+    # 确保参数是元组格式
+    if params is not None and isinstance(params, list):
+        params = tuple(params)
+    df = pd.read_sql(query, engine, params=params)
+    return df
+
+
+
+# SQL 查询条件
+query = f"SELECT * FROM bid_analysis_liantong  WHERE create_time = '{batch_id}'"
+data = fetch_data_from_mysql(query)
+print(data.columns, "第一轮数据检索成功")
+
+# 字段映射
+column_name_mapping = {
+    "area_qa": "省份",
+    "bidamount_qa": "中标金额",
+    "budget_qa": "预算",
+    "buyer_qa": "采购单位",
+    "com_package_qa": "分包",
+    "projectcode_qa": "项目编号",
+    "projectname_qa": "项目名称",
+    "title_qa": "标题",
+    "s_winner_qa": "中标单位",
+    "score": "标讯总分数",
+    "bidopentime_qa": "开标时间",
+    "publishtime_qa": "发布时间",
+    "toptype_qa": "信息一级分类",
+    "subtype_qa": "信息二级分类",
+    "city_qa": "城市",
+    "district_qa":"区县",
+    "detail_qa":"正文",
+    "href_qa":"原文链接",
+    "est_purchase_time_qa":"预计采购时间",
+    "docstarttime_qa": "招标文件获取开始时间",
+    "docendtime_qa": "招标文件获取截止时间",
+    "bidstarttime_qa": "投标文件递交开始时间",
+    "bidendtime_qa": "投标截止日期",
+    "agency_qa": "招标代理机构",
+    "agencyperson_qa": "招标代理机构联系人",
+    "agencytel_qa": "招标代理机构联系方式",
+    "winnerperson_qa": "中标单位联系人",
+    "winnertel_qa": "中标单位联系电话",
+    "entname_qa": "候选人名称",
+    "sortstr_qa": "候选人名次",
+    "price_qa": "投标报价",
+    "bidway_qa": "投标方式",
+    "winnerorder_qa": "候选人",
+    "buyerperson_qa":"采购单位联系人",
+    "buyertel_qa":"采购单位联系电话",
+    "note_qa":"备注"
+}
+
+
+# 只从 error_type 字段提取数据
+def extract_errors(df):
+    # 定义只从 error_type 中映射的字段
+    qa_fields = list(column_name_mapping.values())
+
+    if "error_type" in df.columns:
+        print("✅ 'error_type' 字段存在,开始提取数据")
+
+        # 处理 error_type 字段,如果它是字符串类型,将其转换为字典
+        df['error_type'] = df['error_type'].apply(lambda x: json.loads(x) if isinstance(x, str) else x)
+
+        # 打印 error_type 字段的前几行,确认其数据类型
+        print("error_type 字段数据示例:")
+        print(df['error_type'].head())
+
+        for qa_field in qa_fields:
+            english_field = next((k for k, v in column_name_mapping.items() if v == qa_field), None)
+            if english_field:
+                print(f"正在提取字段: {qa_field}, 对应的英文字段: {english_field}")
+                # 打印出提取过程中的一些信息
+                df[qa_field] = df['error_type'].apply(
+                    lambda x: x.get(english_field) if isinstance(x, dict) and x.get(english_field) != {} else None
+                )
+
+        # 提取标讯总分数
+        df['标讯总分数'] = df['error_type'].apply(lambda x: x.get("score") if isinstance(x, dict) else None)
+        df['标讯总分数'] = pd.to_numeric(df['标讯总分数'], errors='coerce')  # 转换为数值类型
+
+    print(f"✅ 提取后的数据:{df.head()}")
+    return df
+
+
+# 提取数据
+data = extract_errors(data)
+
+# 检查提取后的数据
+print("提取后的数据:")
+print(data.head())  # 打印前几行数据进行检查
+
+# 检查 error_type 的类型分布
+print("error_type 字段的类型分布:")
+print(data['error_type'].apply(type).value_counts())
+
+# 过滤招标数据和中标数据
+win_types = {"结果","其它"}
+bid_types = {"招标"}
+pre_types = {"预告"}
+other_types = {"拟建","采购意向"}
+
+data_bid = data[data["toptype"].isin(bid_types)].copy()  # 招标数据
+data_win = data[data["toptype"].isin(win_types)].copy()  # 中标数据
+data_pre = data[data["toptype"].isin(pre_types)].copy()  # 预告数据
+data_other = data[data["toptype"].isin(other_types)].copy()# 获取其他数据
+# 打印筛选后的数据行数
+print("筛选后的招标数据行数:", len(data_bid))
+print("筛选后的中标数据行数:", len(data_win))
+print("筛选后的预告数据行数:", len(data_pre))
+print("筛选后的其它数据行数:", len(data_other))
+
+
+# 数据分析函数
+def analyze_column(dataframe, column_name, data_type, batch_id):
+    if column_name not in dataframe.columns:
+        return None
+
+    total = len(dataframe[column_name])
+    correct = dataframe[column_name].isna().sum()
+    error = total - correct
+
+    # accuracy and error rate with percentage symbol
+    accuracy = f'{(correct / total * 100):.2f}%' if total > 0 else "0%"
+    error_rate = f'{(error / total * 100):.2f}%' if total > 0 else "0%"
+
+    # calculate error rate for individual error reasons, rounded to two decimal places
+    error_code_counts = {}
+    not_exist_counts = 0  # 新增:统计以"不存在!"结尾的错误数量
+    not_exist_rate_percent=0
+
+    for item in dataframe[column_name].dropna():
+        if isinstance(item, dict):
+            for error_code, error_desc in item.items():
+                error_code_counts.setdefault(error_code, {'description': error_desc, 'count': 0})['count'] += 1
+
+    result = []
+    for error_code, data in error_code_counts.items():
+        if error_code == '0000':
+            not_exist_counts = data['count']
+            not_exist_rate_percent = ( not_exist_counts / total) * 100 if total > 0 else 0
+            not_exist_rate_percent = f'{not_exist_rate_percent:.2f}%'
+        # calculate the error rate for the individual reason
+        single_error_rate = (data['count'] / error) * 100 if error > 0 else 0
+        single_error_rate_percent = f'{single_error_rate:.2f}%'  # single reason error rate with percentage
+        error_description=data['description']
+        # 安全查询
+        query = "SELECT error_one, error_two FROM error_dict WHERE error = %s"
+        error_df = fetch_data_from_mysql(query, params=(error_description,))
+
+        # 处理查询结果
+        error_one = error_two = None
+        if not error_df.empty:
+            error_one = error_df.iloc[0]['error_one']
+            error_two = error_df.iloc[0]['error_two']
+        result.append({
+            'record_type': '字段分析',  # 'record_type' -> record_type
+            'field_name': column_name,  # 'field_name' -> field_name
+            'data_type': data_type,  # 'data_type' -> data_type
+            'batch_id': batch_id,  # 'batch_id' -> batch_id
+            'total_count': total,  # 'total_count' -> total_count
+            'correct_count': correct,  # 'correct_count' -> correct_count
+            'error_count': error,  # 'error_count' -> error_count
+            'accuracy': accuracy,  # 'accuracy' -> accuracy
+            'error_rate': error_rate,  # 'error_rate' -> error_rate
+            'error_code': error_code,  # 'error_code' -> error_code
+            'error_description': data['description'],  # 'error_description' -> error_description
+            'field_count': data['count'],  # 'field_count' -> field_count
+            'single_error_rate': single_error_rate_percent,  # 'single_error_rate' -> single_error_rate
+            'error_one':error_one,
+            'error_two':error_two,
+            "not_exist_counts":not_exist_counts,
+            "not_exist_rate_percent":not_exist_rate_percent,
+            "data_source":1
+        })
+
+
+    return result if result else None
+
+
+
+
+# 分析招标和中标数据
+def analyze_data(df, selected_fields, data_type,batch_id):
+    results = []
+    for field in selected_fields:
+        analysis_result = analyze_column(df, field, data_type, batch_id)
+        if analysis_result:
+            results.extend(analysis_result)
+    return pd.DataFrame(results)
+
+
+# 定义需要分析的字段
+win_selected_fields = ["信息一级分类", "信息二级分类", "省份", "城市","区县", "采购单位", "项目名称", "标题","项目编号", "预算",
+                       "中标单位", "中标金额","中标单位联系人","中标单位联系电话","候选人名称","候选人名次","投标报价","候选人",
+                       "招标代理机构","招标代理机构联系人","招标代理机构联系方式",
+                       "采购单位联系人", "采购单位联系电话",
+                       "正文","发布时间","投标方式","原文链接"]
+bid_selected_fields = ["信息一级分类", "信息二级分类", "省份", "城市","区县", "采购单位", "项目名称", "标题" ,"项目编号", "预算",
+                       "开标时间","招标文件获取开始时间","招标文件获取截止时间","投标文件递交开始时间","投标截止日期",
+                        "采购单位联系人","采购单位联系电话",
+                       "招标代理机构","招标代理机构联系人","招标代理机构联系方式",
+                        "正文","发布时间","原文链接","投标方式"]
+pre_selected_fields = ["信息一级分类", "信息二级分类", "省份", "城市", "区县", "采购单位", "项目名称", "标题", "项目编号", "预算",
+                        "正文","预计采购时间","原文链接","备注","发布时间"]    # 预告 15个
+other_selected_fields = ["信息一级分类", "信息二级分类", "省份", "城市", "区县","采购单位", "项目名称","标题","项目编号", "预算",
+                        "正文","发布时间","原文链接","开标时间","投标方式",
+                        "采购单位联系人", "采购单位联系电话",
+                        "招标代理机构", "招标代理机构联系人", "招标代理机构联系方式",
+                        "中标单位", "中标金额","中标单位联系人","中标单位联系电话"]     #拟建和采购意向
+
+# 分析结果
+win_analysis_df = analyze_data(data_win, win_selected_fields, "结果",batch_id)
+bid_analysis_df = analyze_data(data_bid, bid_selected_fields, "招标",batch_id)
+pre_analysis_df = analyze_data(data_pre, bid_selected_fields, "预告",batch_id)
+other_analysis_df = analyze_data(data_other, other_selected_fields, "其它",batch_id)
+
+# 查看分析结果
+print("结果数据分析结果:", win_analysis_df.head())
+print("招标数据分析结果:", bid_analysis_df.head())
+print("预告数据分析结果:", pre_analysis_df.head())
+print("其它数据分析结果:", other_analysis_df.head())
+
+
+# 分数分析
+def analyze_scores(df):
+    if '标讯总分数' not in df.columns:
+        return []
+
+    total_count = len(df['标讯总分数'])
+    score_counts = df['标讯总分数'].value_counts().sort_index()
+    score_percentage = (score_counts / total_count * 100).round(2).astype(str) + '%'
+
+    score_analysis = []
+    for score, count in score_counts.items():
+        score_analysis.append({
+            "record_type": "分数分析",
+            "score": str(score),
+            "count": int(count),
+            "total": total_count,
+            "percentage": score_percentage[score],
+            "batch_id": batch_id,
+            "data_source":1
+        })
+    return score_analysis
+
+
+# 分数分析结果
+score_analysis_data = analyze_scores(pd.concat([data_bid, data_win,data_pre, data_other]))
+print("分数分析结果:", score_analysis_data)
+
+
+# 存储到 MySQL
+def store_analysis_to_mysql(df, table_name):
+    if df.empty:
+        print(f"⚠️ {table_name} 数据为空,跳过存储")
+        return
+
+    connection = pymysql.connect(**mysql_config)
+    cursor = connection.cursor()
+
+    if table_name == "analysis_results_liantong":
+        sql = """
+        INSERT INTO analysis_results_liantong 
+        (record_type, field_name, data_type, batch_id, total_count, correct_count, error_count, accuracy, error_rate, error_code, error_description, field_count, single_error_rate,error_one,error_two,not_exist_counts,not_exist_rate_percent,data_source)
+        VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,%s,%s,%s,%s,%s)
+        """
+
+    elif table_name == "analysis_score_liantong":
+        sql = """
+        INSERT INTO analysis_score_liantong 
+        (record_type, score, count, total, percentage, batch_id, data_source)
+        VALUES (%s, %s, %s, %s, %s, %s,%s)
+        """
+
+    for _, row in df.iterrows():
+        values = tuple(row.fillna("").values)
+
+        if len(values) != sql.count('%s'):
+            print(f"❌ 参数数量不匹配: 预期 {sql.count('%s')},实际 {len(values)},跳过此行")
+            continue
+
+        cursor.execute(sql, values)
+
+    connection.commit()
+    cursor.close()
+    connection.close()
+    print(f"✅ {table_name} 数据已存储到 MySQL")
+
+
+store_analysis_to_mysql(win_analysis_df, "analysis_results_liantong")
+store_analysis_to_mysql(bid_analysis_df, "analysis_results_liantong")
+store_analysis_to_mysql(pre_analysis_df, "analysis_results_liantong")
+store_analysis_to_mysql(other_analysis_df, "analysis_results_liantong")
+
+store_analysis_to_mysql(pd.DataFrame(score_analysis_data), "analysis_score_liantong")
+
+print("✅ 分析完成,数据已存入 MySQL!")

+ 269 - 0
tools/数据质量监控平台/预算基础信息分析结果入库_联通.py

@@ -0,0 +1,269 @@
+from datetime import date, timedelta,datetime
+import pandas as pd
+import pymysql
+from sqlalchemy import create_engine
+import json
+
+# MySQL 连接配置
+mysql_config = {
+    "host": "172.20.45.129",
+    "port": 4000,
+    "user": "root",
+    "password": "=PDT49#80Z!RVv52_z",
+    "database": "quality"
+}
+
+# SQLAlchemy 连接字符串
+engine = create_engine(
+    f'mysql+pymysql://{mysql_config["user"]}:{mysql_config["password"]}@{mysql_config["host"]}:{mysql_config["port"]}/{mysql_config["database"]}')
+
+def get_this_week_thursday():
+    today = date.today()
+    delta = (3 - today.weekday()) % 7  # 计算到本周四的天数差(兼容跨周)
+    return today + timedelta(days=delta)
+
+# 动态获取本周四的日期
+# query_create_time = get_this_week_thursday().strftime("%Y-%m-%d")  # ✅ 动态获取
+# query_create_time = '2025-04-02'
+now_date = (datetime.now()).strftime("%Y-%m-%d")
+# yesterday_date = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
+batch_id = now_date
+# batch_id = '2025-07-28'
+print(batch_id)
+
+
+# 从 MySQL 获取数据
+def fetch_data_from_mysql(query, params=None):
+    # 确保参数是元组格式
+    if params is not None and isinstance(params, list):
+        params = tuple(params)
+    df = pd.read_sql(query, engine, params=params)
+    return df
+
+
+
+# SQL 查询条件
+query = f"SELECT * FROM yusuan_analysis_liantong  WHERE create_time = '{batch_id}'"
+data = fetch_data_from_mysql(query)
+print(data.columns, "第一轮数据检索成功")
+
+# 字段映射
+column_name_mapping = {
+    "area_qa": "省份",
+    "city_qa": "城市",
+    "district_qa" :"区县",
+    "projectname_qa":"项目名称",
+    "procure_content_qa": "项目概况",
+    "publish_org_qa" :"发文单位",
+    "kpi_qa" :"项目目标",
+    "budget_qa" :"预算",
+    "institution_qa" :"项目单位",
+    "score": "标讯总分数",
+}
+# 只从 error_type 字段提取数据
+def extract_errors(df):
+    # 定义只从 error_type 中映射的字段
+    qa_fields = list(column_name_mapping.values())
+
+    if "error_type" in df.columns:
+        print("✅ 'error_type' 字段存在,开始提取数据")
+
+        # 处理 error_type 字段,如果它是字符串类型,将其转换为字典
+        df['error_type'] = df['error_type'].apply(lambda x: json.loads(x) if isinstance(x, str) else x)
+
+        # 打印 error_type 字段的前几行,确认其数据类型
+        print("error_type 字段数据示例:")
+        print(df['error_type'].head())
+
+        for qa_field in qa_fields:
+            english_field = next((k for k, v in column_name_mapping.items() if v == qa_field), None)
+            if english_field:
+                print(f"正在提取字段: {qa_field}, 对应的英文字段: {english_field}")
+                # 打印出提取过程中的一些信息
+                df[qa_field] = df['error_type'].apply(
+                    lambda x: x.get(english_field) if isinstance(x, dict) and x.get(english_field) != {} else None
+                )
+
+        # 提取标讯总分数
+        df['标讯总分数'] = df['error_type'].apply(lambda x: x.get("score") if isinstance(x, dict) else None)
+        df['标讯总分数'] = pd.to_numeric(df['标讯总分数'], errors='coerce')  # 转换为数值类型
+
+    print(f"✅ 提取后的数据:{df.head()}")
+    return df
+
+
+# 提取数据
+data = extract_errors(data)
+
+# 检查提取后的数据
+print("提取后的数据:")
+print(data.head())  # 打印前几行数据进行检查
+
+# 检查 error_type 的类型分布
+print("error_type 字段的类型分布:")
+print(data['error_type'].apply(type).value_counts())
+
+data_bid = data.copy()  # 预算数据
+
+# 打印筛选后的数据行数
+print("筛选后的预算数据行数:", len(data_bid))
+
+
+# 数据分析函数
+def analyze_column(dataframe, column_name, data_type, batch_id):
+    if column_name not in dataframe.columns:
+        return None
+
+    total = len(dataframe[column_name])
+    correct = dataframe[column_name].isna().sum()
+    error = total - correct
+
+    # accuracy and error rate with percentage symbol
+    accuracy = f'{(correct / total * 100):.2f}%' if total > 0 else "0%"
+    error_rate = f'{(error / total * 100):.2f}%' if total > 0 else "0%"
+
+    # calculate error rate for individual error reasons, rounded to two decimal places
+    error_code_counts = {}
+    not_exist_counts = 0  # 新增:统计以"不存在!"结尾的错误数量
+    not_exist_rate_percent=0
+
+    for item in dataframe[column_name].dropna():
+        if isinstance(item, dict):
+            for error_code, error_desc in item.items():
+                error_code_counts.setdefault(error_code, {'description': error_desc, 'count': 0})['count'] += 1
+
+    result = []
+    for error_code, data in error_code_counts.items():
+        if error_code == '0000':
+            not_exist_counts = data['count']
+            not_exist_rate_percent = ( not_exist_counts / total) * 100 if total > 0 else 0
+            not_exist_rate_percent = f'{not_exist_rate_percent:.2f}%'
+        # calculate the error rate for the individual reason
+        single_error_rate = (data['count'] / error) * 100 if error > 0 else 0
+        single_error_rate_percent = f'{single_error_rate:.2f}%'  # single reason error rate with percentage
+        error_description=data['description']
+        # 安全查询
+        query = "SELECT error_one, error_two FROM error_dict WHERE error = %s"
+        error_df = fetch_data_from_mysql(query, params=(error_description,))
+
+        # 处理查询结果
+        error_one = error_two = None
+        if not error_df.empty:
+            error_one = error_df.iloc[0]['error_one']
+            error_two = error_df.iloc[0]['error_two']
+        result.append({
+            'record_type': '字段分析',  # 'record_type' -> record_type
+            'field_name': column_name,  # 'field_name' -> field_name
+            'data_type': data_type,  # 'data_type' -> data_type
+            'batch_id': batch_id,  # 'batch_id' -> batch_id
+            'total_count': total,  # 'total_count' -> total_count
+            'correct_count': correct,  # 'correct_count' -> correct_count
+            'error_count': error,  # 'error_count' -> error_count
+            'accuracy': accuracy,  # 'accuracy' -> accuracy
+            'error_rate': error_rate,  # 'error_rate' -> error_rate
+            'error_code': error_code,  # 'error_code' -> error_code
+            'error_description': data['description'],  # 'error_description' -> error_description
+            'field_count': data['count'],  # 'field_count' -> field_count
+            'single_error_rate': single_error_rate_percent,  # 'single_error_rate' -> single_error_rate
+            'error_one':error_one,
+            'error_two':error_two,
+            "not_exist_counts":not_exist_counts,
+            "not_exist_rate_percent":not_exist_rate_percent,
+            "data_source": 4
+        })
+    return result if result else None
+
+# 分析招标和中标数据
+def analyze_data(df, selected_fields, data_type,batch_id):
+    results = []
+    for field in selected_fields:
+        analysis_result = analyze_column(df, field, data_type, batch_id)
+        if analysis_result:
+            results.extend(analysis_result)
+    return pd.DataFrame(results)
+
+
+# 定义需要分析的字段
+
+bid_selected_fields = ["省份", "城市","区县","项目名称","项目概况", "发文单位", "项目目标","预算"]
+
+# 分析结果
+bid_analysis_df = analyze_data(data_bid, bid_selected_fields, "预算",batch_id)
+
+
+# 查看分析结果
+print("预算数据分析结果:", bid_analysis_df.head())
+
+
+
+# 分数分析
+def analyze_scores(df):
+    if '标讯总分数' not in df.columns:
+        return []
+
+    total_count = len(df['标讯总分数'])
+    score_counts = df['标讯总分数'].value_counts().sort_index()
+    score_percentage = (score_counts / total_count * 100).round(2).astype(str) + '%'
+
+    score_analysis = []
+    for score, count in score_counts.items():
+        score_analysis.append({
+            "record_type": "分数分析",
+            "score": str(score),
+            "count": int(count),
+            "total": total_count,
+            "percentage": score_percentage[score],
+            "batch_id": batch_id,
+            "data_source":4
+        })
+    return score_analysis
+
+
+# 分数分析结果
+score_analysis_data = analyze_scores(pd.concat([data_bid]))
+print("分数分析结果:", score_analysis_data)
+
+
+# 存储到 MySQL
+def store_analysis_to_mysql(df, table_name):
+    if df.empty:
+        print(f"⚠️ {table_name} 数据为空,跳过存储")
+        return
+
+    connection = pymysql.connect(**mysql_config)
+    cursor = connection.cursor()
+
+    if table_name == "analysis_results_liantong":
+        sql = """
+        INSERT INTO analysis_results_liantong 
+        (record_type, field_name, data_type, batch_id, total_count, correct_count, error_count, accuracy, error_rate, error_code, error_description, field_count, single_error_rate,error_one,error_two,not_exist_counts,not_exist_rate_percent,data_source)
+        VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,%s,%s,%s,%s,%s)
+        """
+
+    elif table_name == "analysis_score_liantong":
+        sql = """
+        INSERT INTO analysis_score_liantong 
+        (record_type, score, count, total, percentage, batch_id,data_source)
+        VALUES (%s, %s, %s, %s, %s, %s,%s)
+        """
+
+    for _, row in df.iterrows():
+        values = tuple(row.fillna("").values)
+
+        if len(values) != sql.count('%s'):
+            print(f"❌ 参数数量不匹配: 预期 {sql.count('%s')},实际 {len(values)},跳过此行")
+            continue
+
+        cursor.execute(sql, values)
+
+    connection.commit()
+    cursor.close()
+    connection.close()
+    print(f"✅ {table_name} 数据已存储到 MySQL")
+
+
+
+store_analysis_to_mysql(bid_analysis_df, "analysis_results_liantong")
+store_analysis_to_mysql(pd.DataFrame(score_analysis_data), "analysis_score_liantong")
+
+print("✅ 分析完成,数据已存入 MySQL!")

+ 53 - 8
tools/标准样本数据入库/execl_into_mongo.py

@@ -1,16 +1,16 @@
 import pandas as pd
 from pymongo import MongoClient
-from bson.objectid import ObjectId
+from bson import ObjectId, json_util
 
 # 连接到 MongoDB
-client = MongoClient('mongodb://192.168.3.149:27180/')
+client = MongoClient('172.20.45.129', 27002, unicode_decode_error_handler="ignore")
 db = client['data_quality']  # 替换为你的数据库名称
-collection = db['standard_sample_data_all']  # 替换为你的集合名称
+collection = db['standard_sample_data']  # 替换为你的集合名称
 
 
 
 # 读取 Excel 文件中的 '标准样本数据汇总' 工作表
-file_path = '/Users/miaobao/Downloads/标准样本数据汇总.xlsx'
+file_path = '/Users/miaobao/Downloads/标准样本数据汇总 (3).xlsx'
 sheet_name = '标准样本数据汇总'
 
 # 使用 pandas 读取 Excel 记录
@@ -24,12 +24,57 @@ df[columns_to_check] = df[columns_to_check].where(pd.notnull(df[columns_to_check
 # 将 _id 列转换为 ObjectId 类型
 df['_id'] = df['_id'].apply(lambda x: ObjectId(str(x)) if x != '' else x)
 
+# 处理 projectname 中的引号(移除转义反斜杠)
+df['projectname'] = df['projectname'].str.replace(r'\\"', '"')  # 替换转义后的引号为普通引号
+
+
 # 将 DataFrame 转换为字典列表
 data = df.to_dict(orient='records')
 
-# 插入数据到 MongoDB
+# 插入数据到 MongoDB,跳过已存在的 _id
 if data:
-    collection.insert_many(data)
-    print("数据已成功插入到 MongoDB")
+    inserted_count = 0
+    skipped_count = 0
+
+    for record in data:
+        try:
+                # 检查 _id 是否已存在
+                if record['_id'] and collection.count_documents({'_id': record['_id']}) > 0:
+                    print(f"跳过已存在的记录 _id: {record['_id']}")
+                    skipped_count += 1
+                    continue
+                # 1. 将 ObjectId 转为字符串(临时解决序列化问题)
+                if '_id' in record and isinstance(record['_id'], ObjectId):
+                    record['_id'] = str(record['_id'])
+
+                # 2. 手动处理引号(确保不被转义)
+                if 'projectname' in record:
+                    record['projectname'] = record['projectname'].replace('\\"', '"')
+
+                # 3. 使用 json_util 处理特殊类型
+                record_json = json_util.dumps(record)
+                record_for_db = json_util.loads(record_json)
+
+                # 4. 还原 ObjectId
+                if '_id' in record_for_db and isinstance(record['_id'], str):
+                    record_for_db['_id'] = ObjectId(record['_id'])
+
+                # 5. 插入数据
+                collection.replace_one(
+                    {"_id": record_for_db.get("_id", ObjectId())},
+                    record_for_db,
+                    upsert=True
+                )
+
+                inserted_count += 1
+                print(f"成功插入记录 _id: {record.get('_id', '无 _id')}")
+
+        except Exception as e:
+            skipped_count += 1
+            print(f"插入失败记录 _id: {record.get('_id', '无 _id')}")
+            print(f"失败原因: {str(e)}")
+            print(f"失败记录内容: {record}\n")
+
+    print(f"\n数据插入完成 - 成功插入: {inserted_count}, 跳过: {skipped_count}")
 else:
-    print("没有数据可插入")
+     print("没有数据可插入")

BIN
tools/生成标准样本库的分析数据/数据分析结果.xlsx


+ 24 - 15
tools/生成标准样本库的分析数据/根据样本数据拉取正式数据生成分析表mongo.py

@@ -2,19 +2,26 @@ from pymongo import MongoClient
 from bson import ObjectId  # 导入 ObjectId
 from lib.mogodb_helper import MongoDBInterface
 
+# # MongoDB 配置信息
+# MongodbConfigLocal = {
+#     "ip_port": "172.20.45.129",
+#     "port": 27002,
+#     "db": "data_quality",
+#     "collection_a": "standard_sample_data",
+# }
 # MongoDB 配置信息
 MongodbConfigLocal = {
-    "ip_port": "172.20.45.129",
-    "port": 27002,
-    "db": "data_quality",
-    "collection_a": "temp_bidding_copy",
+    "ip_port": "127.0.0.1:27088",
+    "user": "viewdata",
+    "password": "viewdata",
+    "db": "qfw",
+    "col": "bidding"  # 替换为实际集合名称
 }
 
 MongodbConfigAnalysis = {
-    "host": "172.20.45.129",
-    "port": 27002,
+    "host": "172.20.45.129:27002",
     "db": "data_quality",
-    "collection_a": "standard_sample_data_new",
+    "collection": "standard_sample_data",
 }
 
 # 字段映射
@@ -33,13 +40,14 @@ field_mapping = {
 
 def main():
     # 连接 MongoDB
-    mongo_interface_src = MongoDBInterface(MongodbConfigLocal)  # 源数据库
-    mongo_interface_dst = MongoDBInterface(MongodbConfigAnalysis)  # 目标数据库
-
-
+    # mongo_interface_src = MongoDBInterface(MongodbConfigLocal)  # 源数据库
+    # mongo_interface_dst = MongoDBInterface(MongodbConfigAnalysis)  # 目标数据库
+    client = MongoClient('172.20.45.129', 27002, unicode_decode_error_handler="ignore").data_quality
+    mongo_interface_src =client['zktest_flash4.0']
+    mongo_interface_dst = client['standard_sample_data']
     # 获取 `sample_bid_analysis` 表中的 `_id` 列表
-    sample_analysis_collection = mongo_interface_dst.get_collection()
-    analysis_ids = sample_analysis_collection.distinct("_id")  # 获取所有 _id
+    # sample_analysis_collection = mongo_interface_dst.get_collection()
+    analysis_ids = mongo_interface_dst.distinct("_id")  # 获取所有 _id
 
     for _id in analysis_ids:
         try:
@@ -49,7 +57,8 @@ def main():
             continue
 
         # 查询 `bidding` 表数据
-        bidding_data = mongo_interface_src.find_by_id(MongodbConfigLocal["col"], object_id)
+        # bidding_data = mongo_interface_src.find_by_id(MongodbConfigLocal["col"], object_id)
+        bidding_data = mongo_interface_src.find_one({"_id":object_id})
         if not bidding_data:
             continue
 
@@ -60,7 +69,7 @@ def main():
         }
 
         # 更新 `sample_bid_analysis` 表
-        sample_analysis_collection.update_one(
+        mongo_interface_dst.update_one(
             {"_id": object_id},  # 依据 _id 匹配
             {"$set": update_fields}  # 更新字段
         )

+ 196 - 47
tools/生成标准样本库的分析数据/生成统计结果.py

@@ -1,8 +1,7 @@
-import pymysql
-import pymongo
 import pandas as pd
-from openpyxl import Workbook
+from bson import ObjectId
 from openpyxl.styles import Font, Alignment
+from pymongo import MongoClient
 
 # # MySQL 配置信息
 # MYSQL_CONFIG = {
@@ -24,29 +23,195 @@ MONGO_CONFIG = {
     "host": "172.20.45.129",
     "port": 27002,
     "db": "data_quality",
-    "col": "standard_sample_data_new",
+    "col": "standard_sample_data",
 }
 
+# 判断 projectname 是否互为包含关系
+def is_contained(str1, str2):
+    """ 判断 str1 和 str2 是否互相包含(非空值情况下) """
+    if pd.isna(str1) or pd.isna(str2):  # 如果有 NaN 值,直接返回 False
+        return False
+    return str1 in str2 or str2 in str1 or str1==str2  # 互为包含
 
 # 连接 MongoDB 并读取数据
 def fetch_data():
-    client = pymongo.MongoClient(f"mongodb://{MONGO_CONFIG['host']}:{MONGO_CONFIG['port']}")
-    db = client[MONGO_CONFIG["db"]]
-    collection = db[MONGO_CONFIG["col"]]
-
-    # 读取数据并转换为 DataFrame
-    data = list(collection.find({}, {"_id": 0}))  # 去掉 `_id` 字段
+    client = MongoClient('172.20.45.129', 27002, unicode_decode_error_handler="ignore").data_quality
+    collection = client['standard_sample_data']
+    data = list(collection.find())
     df = pd.DataFrame(data)
+    return df, collection  # 返回DataFrame和MongoDB集合对象
 
-    client.close()
-    return df
 
-# 判断 projectname 是否互为包含关系
-def is_contained(str1, str2):
-    """ 判断 str1 和 str2 是否互相包含(非空值情况下) """
-    if pd.isna(str1) or pd.isna(str2):  # 如果有 NaN 值,直接返回 False
-        return False
-    return str1 in str2 or str2 in str1  # 互为包含
+# def compared_field(original_value, ai_value):
+#     # 1. 移除所有反斜杠(包括转义符)
+#     original = original_value.replace("\\", "")
+#     ai = ai_value.replace("\\", "")
+#
+#     # 2. 统一引号格式:将所有英文引号(直引号)转为中文引号
+#     # 包括:直双引号 " 和转义后的 \"
+#     original = original.replace('"', '“').replace('“', '“')  # 确保无残留
+#     ai = ai.replace('"', '“').replace('“', '“')
+#
+#     # 替换中文括号、破折号等,但不影响引号
+#     original = (
+#         str(original)
+#             .replace("(", "(")
+#             .replace(")", ")")
+#             .replace("【", "[")
+#             .replace("】", "]")
+#             .replace("—", "-")
+#             .replace("/", "")
+#     )
+#
+#     ai = (
+#         str(ai)
+#             .replace("(", "(")
+#             .replace(")", ")")
+#             .replace("【", "[")
+#             .replace("】", "]")
+#             .replace("—", "-")
+#             .replace("/", "")
+#     )
+#     return original, ai
+
+def unify_quotes_new(text):
+    if not isinstance(text, str):
+        return text
+
+    # 将所有中文引号转为英文直引号(无方向性)
+    text = text.replace('“', '"').replace('”', '"')
+    return text
+
+
+def compared_field(original, ai):
+
+    original = unify_quotes_new(str(original))
+    ai = unify_quotes_new(str(ai))
+
+    print(f"\n原始输入: original={repr(original)}, ai={repr(ai)}")  # 使用repr显示真实字符
+
+    if pd.isna(original) or pd.isna(ai):
+        print("存在空值,直接返回")
+        return original, ai
+
+    # 强制转换为字符串并打印中间过程
+    str_original = str(original)
+    str_ai = str(ai)
+    print(f"转换为字符串后: original={repr(str_original)}, ai={repr(str_ai)}")
+
+    # 移除所有反斜杠
+    no_backslash_original = str_original.replace("\\", "")
+    no_backslash_ai = str_ai.replace("\\", "")
+    print(f"移除反斜杠后: original={repr(no_backslash_original)}, ai={repr(no_backslash_ai)}")
+
+    # 统一所有引号类型(覆盖6种常见情况)
+    quote_map = {
+        '"': '“',  # 英文直双引号
+        "'": '‘',  # 英文直单引号
+        "“": "“",  # 中文左双引号(保持不变)
+        "”": "”",  # 中文右双引号(保持不变)
+        "‘": "‘",  # 中文左单引号
+        "’": "’"  # 中文右单引号
+    }
+
+    def unify_quotes(text):
+        for src, tgt in quote_map.items():
+            text = text.replace(src, tgt)
+        return text
+
+    unified_original = unify_quotes(no_backslash_original)
+    unified_ai = unify_quotes(no_backslash_ai)
+    print(f"统一引号后: original={repr(unified_original)}, ai={repr(unified_ai)}")
+
+    # 其他字符统一化(括号、空格等)
+    trans_table = str.maketrans({
+        "(": "(",
+        ")": ")",
+        " ": " ",  # 处理不间断空格等
+        "\u3000": " ",  # 全角空格转普通空格
+        "【": "[",
+        "】": "]",
+        "—": "-",
+        "/": ""
+    })
+
+    final_original = unified_original.translate(trans_table)
+    final_ai = unified_ai.translate(trans_table)
+    print(f"最终结果: original={repr(final_original)}, ai={repr(final_ai)}")
+
+    return final_original, final_ai
+
+def mark_mismatch_fields(df, collection, category):
+    """在MongoDB中标记不匹配的字段"""
+    # 确定数据类别:中标类 or 招标类
+    if category == "中标类":
+        bid_types = ["成交", "单一", "废标", "合同", "结果变更", "流标", "验收", "中标", "其它"]
+        df = df[df["subtype"].isin(bid_types)]
+        fields = ["toptype", "subtype", "area", "city", "buyer", "projectname", "projectcode", "budget", "s_winner",
+                  "bidamount"]
+    else:  # 招标类
+        bid_types = ["成交", "单一", "废标", "合同", "结果变更", "流标", "验收", "中标", "其它", "拟建"]
+        df = df[~df["subtype"].isin(bid_types)]
+        fields = ["toptype", "subtype", "area", "city", "buyer", "projectname", "projectcode", "budget"]
+
+    # 统一将 None、<NA> 和空字符串都转为 pd.NA
+    df = df.replace({None: pd.NA, '': pd.NA})
+    df = df.fillna(pd.NA)
+
+    # 获取所有文档ID
+    doc_ids = df["_id"].tolist()
+
+    # 先清除所有文档的mismatch_fields字段
+    collection.update_many(
+        {"_id": {"$in": doc_ids}},
+        {"$unset": {"mismatch_fields": ""}}
+    )
+
+    # 遍历每一行数据
+    for _, row in df.iterrows():
+        mismatch_fields = []
+
+        # 遍历每个字段
+        for field in fields:
+            original_value = row.get(field, pd.NA)
+            ai_value = row.get(f"{field}_ai", pd.NA)
+
+            # 判断是否匹配
+            if field == "projectname":
+                original_value, ai_value = compared_field(original_value,ai_value)
+                is_match = is_contained(original_value, ai_value)
+            else:
+                if pd.isna(original_value) or pd.isna(ai_value):
+                    is_match = pd.isna(original_value) and pd.isna(ai_value)
+                else:
+                    is_match = original_value == ai_value
+
+            # 如果不匹配,记录字段名和原因
+            if not is_match:
+                mismatch_info = {"field": field}
+
+                # 确定不匹配的原因
+                if pd.isna(original_value) and not pd.isna(ai_value):
+                    mismatch_info["reason"] = "原文为空但AI有值"
+                elif not pd.isna(original_value) and pd.isna(ai_value):
+                    mismatch_info["reason"] = "原文有值但AI为空"
+                elif field == "projectname":
+                    mismatch_info["reason"] = "项目名称不互为包含"
+                else:
+                    mismatch_info["reason"] = "值不匹配"
+
+                # 保存原始值和AI值
+                mismatch_info["original_value"] = str(original_value) if not pd.isna(original_value) else None
+                mismatch_info["ai_value"] = str(ai_value) if not pd.isna(ai_value) else None
+
+                mismatch_fields.append(mismatch_info)
+
+        # 如果有不匹配的字段,更新MongoDB文档
+        if mismatch_fields:
+            collection.update_one(
+                {"_id": row["_id"]},
+                {"$set": {"mismatch_fields": mismatch_fields}}
+            )
 
 # 计算统计数据
 def calculate_metrics_and_accuracy(df, category):
@@ -78,6 +243,7 @@ def calculate_metrics_and_accuracy(df, category):
             ai_value = row.get(f"{field}_ai", pd.NA)
 
             if field == "projectname":  # 特殊处理 projectname
+                original_value, ai_value = compared_field(original_value, ai_value)
                 is_correct = is_contained(original_value, ai_value)
             else:
                 # 这里避免 pd.NA 直接比较导致错误
@@ -101,7 +267,13 @@ def calculate_metrics_and_accuracy(df, category):
         valid_count = total_count - null_count  # 原文有值的数量
 
         if field == "projectname":  # 特殊处理 projectname
-            extract_correct_count = df.apply(lambda row: is_contained(row["projectname"], row["projectname_ai"]),axis=1).sum()
+            # 预处理原始值和AI值(如括号替换等)
+            df["projectname_processed"] = df["projectname"].apply(
+                lambda x: compared_field(x, x)[0] if pd.notna(x) else x)
+            df["projectname_ai_processed"] = df["projectname_ai"].apply(
+                lambda x: compared_field(x, x)[0] if pd.notna(x) else x)
+
+            extract_correct_count = df.apply(lambda row: is_contained(row["projectname_processed"], row["projectname_ai_processed"]),axis=1).sum()
             extract_error_count = valid_count - extract_correct_count
             extract_correct_no_null = extract_correct_count  # 互为包含的都算正确
             extract_error_no_null = extract_error_count
@@ -139,33 +311,6 @@ def calculate_metrics_and_accuracy(df, category):
                               columns=["指标", "数值"])
     return df_fields,df_overall
 
-
-# # 计算整体正确率
-# def calculate_overall_accuracy(df, fields):
-#     """ 计算整行正确的数量及单行正确率 """
-#     total_count = len(df)  # 样本总量
-#
-#     # 判断每行所有字段是否都正确(projectname 需使用互为包含逻辑)
-#     def is_row_correct(row):
-#         for field in fields:
-#             if pd.isna(row[field]) and pd.isna(row[f"{field}_ai"]):  # 如果原值和 AI 值都为空,算正确
-#                 continue
-#             if field == "projectname":
-#                 if not is_contained(row["projectname"], row["projectname_ai"]):  # projectname 互为包含
-#                     return False
-#             else:
-#                 if row[field] != row.get(f"{field}_ai", row[field]):  # 其他字段直接对比
-#                     return False
-#         return True
-#
-#     correct_rows = df.apply(is_row_correct, axis=1).sum()  # 统计整行正确的数量
-#     single_row_accuracy = correct_rows / total_count if total_count else 0  # 计算单行正确率
-#
-#     return pd.DataFrame([["数据总量", total_count],
-#                          ["整行都正确的数量", correct_rows],
-#                          ["单行正确率", f"{single_row_accuracy:.2%}"]],
-#                         columns=["指标", "数值"])
-
 # 导出 Excel
 def export_to_excel(df_bid_fields, df_bid_overall,df_tender_fields,df_tender_overall):
     file_path = "数据分析结果.xlsx"
@@ -200,7 +345,11 @@ def export_to_excel(df_bid_fields, df_bid_overall,df_tender_fields,df_tender_ove
 
 # 主函数
 def main():
-    df = fetch_data()
+    df, collection = fetch_data()
+    # 先标记不匹配字段
+    mark_mismatch_fields(df, collection, "中标类")
+    mark_mismatch_fields(df, collection, "招标类")
+
     df_bid_fields, df_bid_overall = calculate_metrics_and_accuracy(df, "中标类")
     df_tender_fields, df_tender_overall = calculate_metrics_and_accuracy(df, "招标类")
     export_to_excel(df_bid_fields, df_bid_overall,df_tender_fields,df_tender_overall)

+ 19 - 17
tools/生成标准样本库的分析数据/生成统计结果_入库.py

@@ -1,8 +1,7 @@
 import pymysql
-import pymongo
+from pymongo import MongoClient
 import pandas as pd
-from openpyxl import Workbook
-from openpyxl.styles import Font, Alignment
+from datetime import datetime
 
 # # MySQL 配置信息
 # MYSQL_CONFIG = {
@@ -24,7 +23,7 @@ MONGO_CONFIG = {
     "host": "172.20.45.129",
     "port": 27002,
     "db": "data_quality",
-    "col": "standard_sample_data_new",
+    "col": "standard_sample_data",
 }
 # MySQL 配置
 MYSQL_CONFIG = {
@@ -37,15 +36,13 @@ MYSQL_CONFIG = {
 
 # 连接 MongoDB 并读取数据
 def fetch_data():
-    client = pymongo.MongoClient(f"mongodb://{MONGO_CONFIG['host']}:{MONGO_CONFIG['port']}")
-    db = client[MONGO_CONFIG["db"]]
-    collection = db[MONGO_CONFIG["col"]]
+    # client = pymongo.MongoClient(f"mongodb://{MONGO_CONFIG['host']}:{MONGO_CONFIG['port']}")
+    client = MongoClient('172.20.45.129', 27002, unicode_decode_error_handler="ignore").data_quality
+    collection = client['standard_sample_data']
 
     # 读取数据并转换为 DataFrame
     data = list(collection.find({}, {"_id": 0}))  # 去掉 `_id` 字段
     df = pd.DataFrame(data)
-
-    client.close()
     return df
 
 # 判断 projectname 是否互为包含关系
@@ -159,36 +156,41 @@ def save_to_database(df_fields, df_overall):
     """保存到优化后的数据库结构"""
     conn = pymysql.connect(**MYSQL_CONFIG)
     cursor = conn.cursor()
-
+    batch_id = (datetime.now()).strftime("%Y-%m-%d")
+    create_time=datetime.now()
     try:
         # 插入字段统计
         for _, row in df_fields.iterrows():
             sql = """
             INSERT INTO sample_data_analysis (
-                field_name, sample_total, original_null, original_exist,
+                batch_id,field_name, sample_total, original_null, original_exist,
                 extract_error_total, extract_correct_total, extract_error_exist,
                 extract_correct_exist, recognition_rate, correct_recognition_rate,
-                accuracy_rate, data_type
-            ) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)
+                accuracy_rate, data_type,create_time
+            ) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)
             """
             cursor.execute(sql, (
+                batch_id,
                 row['field_name'], row['sample_total'], row['original_null'],
                 row['original_exist'], row['extract_error_total'],
                 row['extract_correct_total'], row['extract_error_exist'],
                 row['extract_correct_exist'], row['recognition_rate'],
                 row['correct_recognition_rate'], row['accuracy_rate'],
-                row['data_type']
+                row['data_type'],
+                create_time
             ))
         # 插入整体统计
         for _, row in df_overall.iterrows():
             sql = """
             INSERT INTO sample_data_per_line_analysis 
-            (total_data_count, correct_rows_count, row_accuracy, data_type)
-            VALUES (%s,%s,%s,%s)
+            (batch_id,total_data_count, correct_rows_count, row_accuracy, data_type,create_time)
+            VALUES (%s,%s,%s,%s,%s,%s)
             """
             cursor.execute(sql, (
+                batch_id,
                 row['total_data_count'], row['correct_rows_count'],
-                row['row_accuracy'], row['data_type']
+                row['row_accuracy'], row['data_type'],
+                create_time
             ))
 
         conn.commit()

+ 21 - 7
tools/联通项目/data_timeliness.py

@@ -7,8 +7,15 @@ import pandas as pd
 def data_timeliness_analysis():
     try:
         # ==================== MongoDB连接配置 ====================
+        #测试环境
+        # mongo_client = MongoClient(
+        #     'mongodb://127.0.0.1:27087/',
+        #     unicode_decode_error_handler="ignore",
+        #     directConnection=True
+        # )
+        #正式环境86库
         mongo_client = MongoClient(
-            'mongodb://127.0.0.1:27087/',
+            'mongodb://172.20.17.61:27080/',
             unicode_decode_error_handler="ignore",
             directConnection=True
         )
@@ -28,20 +35,27 @@ def data_timeliness_analysis():
         # ==================== 数据统计逻辑 ====================
         # 时间范围设置(当前时间前1小时)
         now = datetime.now()
-        hour_start = (now - timedelta(hours=1)).replace(minute=0, second=0, microsecond=0)
-
+        # hour_start = (now - timedelta(hours=1)).replace(minute=0, second=0, microsecond=0)
+        # 获取今天的日期(字符串格式)
+        today_date = datetime.now().strftime("%Y-%m-%d")
+        yesterday_date = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
+        # 获取昨天 00:00:00 的时间戳
+        start_date = int(datetime.strptime(f"{yesterday_date} 00:00:00", "%Y-%m-%d %H:%M:%S").timestamp())
+        # print("start_date",start_date)
+        # 获取今天 00:00:00 的时间戳
+        end_date = int(datetime.strptime(f"{today_date} 00:00:00", "%Y-%m-%d %H:%M:%S").timestamp())
         # 构建查询条件
         query = {
             "appid": "jyGQ1XQQsEAwNeSENOFR9D",
             "createtime": {
-                "$gte": int(hour_start.timestamp()),
-                "$lt": int(now.replace(minute=0, second=0, microsecond=0).timestamp())
+                "$gte": start_date,
+                "$lt": end_date
             }
         }
 
         # 初始化统计结果
         stats = {
-            'create_time': now.strftime('%Y-%m-%d %H:%M:%S'),
+            'create_time': now.strftime("%Y-%m-%d"),
             'total_count': 0,
             'less_than_2h_count': 0,
             'less_than_2h_ratio': 0.0,
@@ -124,7 +138,7 @@ def data_timeliness_analysis():
         print("✅ 操作完成:")
         print(f"1. Excel报表已生成(数据时效统计表.xlsx)")
         print(f"2. 数据已插入MySQL(quality.data_timeliness_liantong)")
-        print(f"📊 统计时段:{hour_start.strftime('%H:%M')} - {now.strftime('%H:%M')}")
+        print(f"📊 统计时段:{yesterday_date} - {today_date}")
         print(f"📝 统计结果:{stats}")
 
     except Exception as e:

+ 152 - 0
tools/联通项目/data_timeliness_bak.py

@@ -0,0 +1,152 @@
+from pymongo import MongoClient
+import pymysql
+from datetime import datetime, timedelta
+import pandas as pd
+
+
+def data_timeliness_analysis():
+    try:
+        # ==================== MongoDB连接配置 ====================
+        #测试环境
+        # mongo_client = MongoClient(
+        #     'mongodb://127.0.0.1:27087/',
+        #     unicode_decode_error_handler="ignore",
+        #     directConnection=True
+        # )
+        #正式环境86库
+        mongo_client = MongoClient(
+            'mongodb://172.20.17.61:27080/',
+            unicode_decode_error_handler="ignore",
+            directConnection=True
+        )
+        mongo_db = mongo_client["jyqyfw"]
+        collection = mongo_db["usermail"]
+
+        # ==================== MySQL连接配置 ====================
+        mysql_conn = pymysql.connect(
+            host='172.20.45.129',
+            port=4000,
+            user='root',  # 替换实际用户名
+            password='=PDT49#80Z!RVv52_z',  # 替换实际密码
+            database='quality',
+            charset='utf8mb4'
+        )
+
+        # ==================== 数据统计逻辑 ====================
+        # 时间范围设置(当前时间前1小时)
+        now = datetime.now()
+        # hour_start = (now - timedelta(hours=1)).replace(minute=0, second=0, microsecond=0)
+        # 获取今天的日期(字符串格式)
+        today_date = datetime.now().strftime("%Y-%m-%d")
+        yesterday_date = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
+        # 获取昨天 00:00:00 的时间戳
+        start_date = int(datetime.strptime(f"{yesterday_date} 00:00:00", "%Y-%m-%d %H:%M:%S").timestamp())
+        # print("start_date",start_date)
+        # 获取今天 00:00:00 的时间戳
+        end_date = int(datetime.strptime(f"{today_date} 00:00:00", "%Y-%m-%d %H:%M:%S").timestamp())
+        # 构建查询条件
+        query = {
+            "appid": "jyGQ1XQQsEAwNeSENOFR9D",
+            "createtime": {
+                "$gte": start_date,
+                "$lt": end_date
+            }
+        }
+
+        # 初始化统计结果
+        stats = {
+            'create_time': now.strftime("%Y-%m-%d"),
+            'total_count': 0,
+            'less_than_2h_count': 0,
+            'less_than_2h_ratio': 0.0,
+            '2h_to_3h_count': 0,
+            '2h_to_3h_ratio': 0.0,
+            '3h_to_4h_count': 0,
+            '3h_to_4h_ratio': 0.0,
+            '4h_to_8h_count': 0,
+            '4h_to_8h_ratio': 0.0,
+            'more_than_8h_count': 0,
+            'more_than_8h_ratio': 0.0
+        }
+
+        # 执行统计查询
+        total_count = collection.count_documents(query)
+        stats['total_count'] = total_count
+
+        if total_count > 0:
+            # 各时间区间统计
+            for doc in collection.find(query, {"createtime": 1, "publishtime": 1, "_id": 0}):
+                hours_diff = abs(doc["createtime"] - doc["publishtime"]) / 3600
+
+                if hours_diff <= 2:
+                    stats['less_than_2h_count'] += 1
+                elif 2 < hours_diff <= 3:
+                    stats['2h_to_3h_count'] += 1
+                elif 3 < hours_diff <= 4:
+                    stats['3h_to_4h_count'] += 1
+                elif 4 < hours_diff <= 8:
+                    stats['4h_to_8h_count'] += 1
+                else:
+                    stats['more_than_8h_count'] += 1
+
+            # 计算占比(保留2位小数)
+            stats['less_than_2h_ratio'] = round(stats['less_than_2h_count'] / total_count * 100, 2)
+            stats['2h_to_3h_ratio'] = round(stats['2h_to_3h_count'] / total_count * 100, 2)
+            stats['3h_to_4h_ratio'] = round(stats['3h_to_4h_count'] / total_count * 100, 2)
+            stats['4h_to_8h_ratio'] = round(stats['4h_to_8h_count'] / total_count * 100, 2)
+            stats['more_than_8h_ratio'] = round(stats['more_than_8h_count'] / total_count * 100, 2)
+
+        # ==================== 生成Excel报表 ====================
+        excel_data = {
+            "创建时间": [stats['create_time']],
+            "总量": [stats['total_count']],
+            "<=2小时数量": [stats['less_than_2h_count']],
+            "<=2小时占比": [f"{stats['less_than_2h_ratio']}%"],
+            "2-3小时数量": [stats['2h_to_3h_count']],
+            "2-3小时占比": [f"{stats['2h_to_3h_ratio']}%"],
+            "3-4小时数量": [stats['3h_to_4h_count']],
+            "3-4小时占比": [f"{stats['3h_to_4h_ratio']}%"],
+            "4-8小时数量": [stats['4h_to_8h_count']],
+            "4-8小时占比": [f"{stats['4h_to_8h_ratio']}%"],
+            ">8小时数量": [stats['more_than_8h_count']],
+            ">8小时占比": [f"{stats['more_than_8h_ratio']}%"]
+        }
+        pd.DataFrame(excel_data).to_excel("数据时效统计表.xlsx", index=False)
+
+        # ==================== 导入MySQL数据库 ====================
+        with mysql_conn.cursor() as cursor:
+            sql = """
+            INSERT INTO data_timeliness_liantong (
+                create_time, total_count,
+                less_than_2h_count, less_than_2h_ratio,
+                `2h_to_3h_count`, `2h_to_3h_ratio`,
+                `3h_to_4h_count`, `3h_to_4h_ratio`,
+                `4h_to_8h_count`, `4h_to_8h_ratio`,
+                more_than_8h_count, more_than_8h_ratio
+            ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
+            """
+            cursor.execute(sql, (
+                stats['create_time'], stats['total_count'],
+                stats['less_than_2h_count'], stats['less_than_2h_ratio'],
+                stats['2h_to_3h_count'], stats['2h_to_3h_ratio'],
+                stats['3h_to_4h_count'], stats['3h_to_4h_ratio'],
+                stats['4h_to_8h_count'], stats['4h_to_8h_ratio'],
+                stats['more_than_8h_count'], stats['more_than_8h_ratio']
+            ))
+        mysql_conn.commit()
+
+        print("✅ 操作完成:")
+        print(f"1. Excel报表已生成(数据时效统计表.xlsx)")
+        print(f"2. 数据已插入MySQL(quality.data_timeliness_liantong)")
+        print(f"📊 统计时段:{yesterday_date} - {today_date}")
+        print(f"📝 统计结果:{stats}")
+
+    except Exception as e:
+        print(f"❌ 操作失败: {type(e).__name__}: {str(e)}")
+    finally:
+        mongo_client.close()
+        mysql_conn.close()
+
+
+if __name__ == '__main__':
+    data_timeliness_analysis()

+ 940 - 0
tools/联通项目/sites_data.csv

@@ -0,0 +1,940 @@
+网站名,剑鱼收录站点名,重点网站,验证栏目是否收录全,是否需要登录,收录情况-人工,是否无效站点0无效,1有效,僵尸站点,注册不了站点
+512汶川特大地震纪念馆,512汶川特大地震纪念馆,否,是,,,1,1,1
+CEC电子采购平台,CEC电子采购平台,否,是,是(已有账号),,1,1,1
+阿坝藏族羌族自治州公共资源交易中心,阿坝州政府采购网上竞价平台,是,否,,,1,1,1
+阿拉善公共资源交易网,阿拉善盟公共资源交易中心,是,否,,,1,1,1
+安徽建工集团,安徽建工集团集采平台,否,网站变更,,,1,1,1
+安徽省公共资源交易监管网,安徽省公共资源交易监管网,是,否,,,1,1,1
+安徽政府采购网,安徽省政府采购网,是,是,,,1,1,1
+安徽省政府采购网,安徽省政府采购网,是,是,,,1,1,1
+安徽颍上农村商业银行股份有限公司,安徽颍上农村商业银行股份有限公司,否,是,,,1,1,1
+信e采平台,安天智采招标采购电子交易平台,否,是,是(但是不登录能查看信息),,1,1,1
+安阳市公共资源交易中心,安阳市公共资源交易中心,是,否,,,1,1,1
+安装信息网,安装信息网,否,网站失效,,,1,1,1
+鞍钢集团供应商客户信息平台,鞍钢招标有限公司,否,是,,,1,1,1
+澳柯玛股份有限公司,澳柯玛股份有限公司,否,是,,,1,1,1
+八戒公采,八戒公采,否,是,是(已有账号),,1,1,1
+巴中市政府采购网,巴中市政府采购网,是,是,,,1,1,1
+白城市公共资源交易平台,白城市公共资源交易网,是,是,,,1,1,1
+白山市公共资源交易中心,白山市公共资源交易中心,是,已合并省级公共资源中心,,,1,1,1
+上海宝华招标有限公司,宝华招标,否,否,,,1,1,1
+上海宝华国际招标有限公司,宝华招标,否,否,,,1,1,1
+全国公共资源交易平台(陕西省),宝鸡公共资源交易中心,是,是,,,1,1,1
+陕西省公共资源交易平台,宝鸡公共资源交易中心,是,是,,,1,1,1
+宝武钢采购专区,宝武采购电子商务平台,否,网站已作废,,,1,1,1
+北海市海城区人民政府,北海市海城区人民政府,是,否,,,1,1,1
+北极星环保网,北极星环保网,否,是,,,1,1,1
+北极星火力发电网,北极星火力发电网,否,是,,,1,1,1
+北京市公共资源交易服务平台,北京市公共资源交易服务平台,是,否,,,1,1,1
+全国公共资源交易平台(北京市)北京市公共资源交易服务平台,北京市公共资源综合交易系统,是,否,,,1,1,1
+北京市公共资源交易中心,北京市公共资源综合交易系统,是,否,,,1,1,1
+京华云采电子卖场,北京市政府采购电子卖场(京华云采),是,否(需登录的栏目未收录),是(部分栏目需要登录),,1,1,0
+北京市政府采购网,北京市政府采购网,是,否,,,1,1,1
+北汽福田汽车股份有限公司诸城汽车厂,北汽福田电子招标平台,否,是,,,1,1,1
+比德电子采购平台,比德电子采购平台,否,是,,,1,1,1
+滨州公共资源交易中心,滨州公共资源交易中心,是,否,,,1,1,1
+滨州公共资源交易平台,滨州公共资源交易中心,否,否,,,1,1,1
+滨州市人民政府,滨州市人民政府,否,是,,,1,1,1
+新疆兵团政府采购网,兵团政府采购网,是,是,,,1,1,1
+采购与招标网,采购与招标网(元博网),否,否,是(竞品网站-元博网),,1,1,2
+采购招标网,采购招标网,否,否,是(竞品网站-元博网),,1,1,2
+常德市政府采购网,常德市政府采购网,是,是,,,1,1,1
+巢湖市人民政府,巢湖市人民政府,是,是,,,1,1,1
+郴州市公共资源交易中心,郴州市公共资源交易中心,是,否,,,1,1,1
+成都航空,成都航空,否,是,,,1,1,1
+成都建工物资有限责任公司,成都建工物资有限责任公司,否,是,是(部分栏目需登录),,1,1,1
+成都市公共资源交易服务中心,成都市公共资源交易服务中心,是,否,,,1,1,1
+成都中医药大学附属医院德阳医院,成都中医药大学附属医院德阳医院,否,是,,,1,1,1
+诚e招,诚E招电子采购交易平台,否,是,,,1,1,1
+诚E招电子采购交易平台,诚E招电子采购交易平台,否,是,,,1,1,1
+承德热力电子采购门户,承德热力电子采购门户,否,是,是(需登录注册)),,1,1,0
+承德市文物局,承德市文物局,否,是,,,1,1,1
+承宇工程顾问有限公司,承宇工程顾问有限公司,否,否,,,1,1,1
+广州地铁城规采购网,城轨采购网,否,否,是(需登录注册),,1,1,0
+赤峰市公共资源交易中心,赤峰公共资源交易网,是,否,,,1,1,1
+赤峰市市公共资源交易中心,赤峰公共资源交易网,是,否,,,1,1,1
+滁州市第二中学,滁州市第二中学,否,网站已作废,,,1,1,1
+达州市通川区人民检察院,达州市通川区人民检察院,否,否,,,1,1,1
+大连海洋大学信息化工作办公室,大连海洋大学信息化工作办公室,否,是,,,1,1,1
+大连民族大学采购招标管理中心,大连民族大学采购招标管理中心,否,是,否,,1,1,1
+大连市第七人民医院,大连市第七人民医院,否,是,否,,1,1,1
+大连市政府采购网,大连市政府采购网,是,是,否,,1,1,1
+大唐电子商务平台,大唐电子商务平台,否,是,否,,1,1,1
+黑龙江政府采购网(政府网站),大兴安岭地区塔河县政府采购网,是,是,否,,1,1,1
+黑龙江政府采购电子卖场,大兴安岭地区塔河县政府采购网,是,是,否,,1,1,1
+丹徒教育信息网,丹徒教育信息网,否,是,否,,1,1,1
+德阳市罗江区人民政府网,德阳市罗江区人民政府网,是,是,否,,1,1,1
+德阳市人民政府,德阳市人民政府,是,网页跳转至德阳市公共资源交易信息网,该站点已收录,,,1,1,1
+德州市公共资源交易中心,德州市公共资源交易中心平原县,是,是,否,,1,1,1
+定安县人民政府,定安县人民政府,是,否,否,,1,1,1
+东城集团,东城集团,否,是,否,,1,1,1
+东莞市轨道交通有限公司,东莞轨道交通,否,否,否,,1,1,1
+东莞理工学院招标与采购管理中心,东莞理工学院招标与采购管理中心,否,否,否,,1,1,1
+东莞市高埗医院,东莞市高埗医院,否,是,否,,1,1,1
+东莞市厚街医院,东莞市厚街医院,否,是,否,,1,1,1
+东莞市农村集体资产管理网,东莞市农村集体资产管理网,否,是,否,,1,1,1
+东莞市人民医院,东莞市人民医院,否,是,否,,1,1,1
+东莞市财政局,东莞市政府采购网,否,无标讯数据,,,1,1,1
+东海县公共资源交易中心,东海县公共资源交易中心,是,是,否,,1,1,1
+东航集团集采实施平台,东航集团集采实施平台,否,是,否,,1,1,1
+东台市富达资产经营有限公司,东台市富达资产经营有限公司,否,是,否,,1,1,1
+东乡区人民政府,东乡区人民政府,是,否,否,,1,1,1
+东营市政府采购网,东营市政府采购网,是,网页链接打不开,,,1,1,1
+东营银行官网,东营银行股份有限公司,否,是,否,,1,1,1
+方洋集团物资采购平台,方洋集团物资采购平台,否,是,否,,1,1,1
+佛山大学招标采购中心,佛山大学招标采购中心,否,是,否,,1,1,1
+佛山市公共资源交易中心禅城分中心,佛山市禅城区公共资源交易中心,是,是,否,,1,1,1
+佛山市禅城区人民政府,佛山市禅城区人民政府,是,是,否,,1,1,1
+佛山市第一人民医院,佛山市第一人民医院,否,是,否,,1,1,1
+佛山市第一中学,佛山市第一中学,否,是,否,,1,0,
+佛山市保健院,佛山市妇幼保健院,否,是,否,,1,1,1
+佛山市公共资源交易中心,佛山市公共资源交易网,是,部分栏目网站打不开,,,1,1,1
+佛山市公共资源交易信息化综合平台,佛山市公共资源交易网,是,部分栏目网站打不开,,,1,1,1
+佛山市教育局,佛山市教育局,否,是,否,,1,1,1
+佛山市顺德区公共资源交易中心,佛山市顺德区公共资源交易中心,是,否,否,,1,1,1
+佛山市有为招标代理有限公司,佛山市有为招标代理有限公司,否,是,否,,1,0,
+福建省公共资源交易电子公共服务平台,福建省公共资源交易电子公共服务平台,是,是,否,,1,1,1
+福建省水利厅,福建省水利厅,否,是,否,,1,1,1
+福建省政府采购网,福建省政府采购网,是,是,否,,1,1,1
+福州海峡纵横资产租赁交易电子竞价平台,福州海峡纵横资产租赁交易电子竞价平台,否,是,否,,1,1,1
+阜新市水利局,阜新市水利局,否,是,否,,1,1,1
+甘肃省公共资源交易网,甘肃省公共资源交易网,是,否,否,,1,1,1
+甘肃省阳光招标采购平台,甘肃省阳光招标采购平台,否,是,否,,1,1,1
+甘肃政府采购网,甘肃政府采购网,是,是,否,,1,1,1
+甘肃省政府采购网,甘肃政府采购网,是,是,否,,1,1,1
+通信工程建设项目招标投标管理信息平台(工业和信息化部),工信部通信工程建设项目招投标管理信息平台,否,是,否,,1,1,1
+冠县人民医院,冠县人民医院,否,网站变更,,,1,1,1
+光大环境招标采购电子交易平台,光大环境招标采购电子交易平台,否,是,否,,1,1,1
+广东德易招标代理有限公司,广东德易招标代理有限公司,否,否,否,,1,1,1
+广发银行CGB供应商服务平台,广东发展银行,否,是,否,,1,1,1
+广东工业大学采购招标中心,广东工业大学招投标中心,否,是,否,,1,1,1
+广东公采招标有限公司,广东公采招标有限公司,否,是,否,,1,1,1
+广东广招招标采购有限公司,广东广招招标采购有限公司,否,是,否,,1,1,1
+广东国采招标咨询有限公司,广东国采招标咨询有限公司,否,是,否,,1,1,1
+广东国和采购咨询有限公司,广东国和采购咨询有限公司,否,是,否,,1,1,1
+广东和丰招标代理有限公司,广东和丰招标代理有限公司,否,是,否,,1,1,1
+广东和盛招标代理有限公司,广东和盛招标代理有限公司,否,是,否,,1,1,1
+广东华伦,广东华伦招标有限公司,否,是,否,,1,1,1
+广东华禹工程咨询有限公司,广东华禹工程咨询有限公司,否,否,否,,1,1,1
+广东金扬教育采购中心有限公司,广东金扬教育采购中心有限公司,否,是,否,,1,1,1
+广东诺建工程管理有限公司,广东诺建工程管理有限公司,否,网站打不开,,,1,1,1
+广东平正招标采购服务有限公司,广东平正招标采购服务有限公司,否,是,否,,1,1,1
+广东群升招标代理有限公司,广东群升招标代理有限公司,否,否,否,,1,1,1
+三方诚信招标有限公司,广东三方诚信招标有限公司,否,是,否,,1,1,1
+广东省妇幼保健院,广东省妇幼保健院,否,否,否,,1,1,1
+广东省工人医院,广东省工人医院,否,是,否,,1,1,1
+广东省公共资源交易平台,广东省公共资源交易平台,是,是,否,,1,1,1
+广东省广播电视网络股份有限公司,广东省广播电视网络股份有限公司,否,是,否,,1,1,1
+广东省广州监狱,广东省广州监狱,否,,,,1,1,1
+广东省惠州监狱,广东省惠州监狱,否,,,,1,1,1
+广东省机电设备招标中心有限公司电子招标投标交易平台,广东省机电设备招标中心有限公司,否,是,否,,1,1,1
+广东省机械技师学院,广东省机械技师学院,否,是,否,,1,1,1
+广东省网上中介服务超市,广东省网上中介服务超市,否,是,否,,1,1,1
+广东省英德监狱门户网站,广东省英德监狱,否,,,,1,1,1
+广东能源新商务网(广东省能源局),广东省粤电集团有限公司,否,否,否,,1,1,1
+广东省招标投标监管网,广东省招标投标监管网,否,是,否,,1,1,1
+中国政府采购网广东分网,广东省政府采购网,是,网站打不开,系统正在维护,,,1,1,1
+广东省政府采购网,广东省政府采购网,是,网站打不开,系统正在维护,,,1,1,1
+广东省政府采购中心,广东省政府采购中心,是,是,否,,1,1,1
+广东省自然资源厅,广东省自然资源厅,否,否,否,,1,1,1
+广东协作项目管理有限公司,广东协作项目管理有限公司,否,是,否,,1,1,1
+广东业信采购招标有限公司,广东业信采购招标有限公司,否,是,否,,1,1,1
+广东医科大学,广东医科大学,否,是,否,,1,1,1
+广东以色列理工学院,广东以色列理工学院,否,是,否,,1,1,1
+广东远东招标代理有限公司,广东远东招标代理有限公司,否,否,否,,1,1,1
+广东志佳工程顾问有限公司,广东志佳工程顾问有限公司,否,是,否,,1,1,1
+广东志正招标有限公司,广东志正招标有限公司,否,是,否,,1,1,1
+广东志正招标有限公司官网,广东志正招标有限公司,否,是,否,,1,1,1
+广东中采招标有限公司,广东中采招标有限公司,否,是,否,,1,1,1
+广东中元招标代理有限公司,广东中元招标代理有限公司,否,否,否,,1,1,1
+广东众得招标有限公司,广东众得招标有限公司,否,否,否,,1,1,1
+广西北部湾投资集团有限公司电子招采平台,广西北部湾投资集团有限公司电子招采平台,否,否,否,,1,1,1
+广西公共资源交易中心,广西公共资源交易中心,是,是,否,,1,1,1
+广西壮族自治区公共资源交易平台系统,广西公共资源交易中心,是,是,否,,1,1,1
+广西河池市大数据发展局,广西河池市大数据发展局,否,是,否,,1,1,1
+广西交通投资集团集中采购平台,广西交通投资集团集中采购平台,否,否,否,,1,1,1
+广西科文招标有限公司,广西科文招标有限公司,否,是,否,,1,1,1
+广西来宾金秀瑶族自治县人民政府,广西来宾金秀瑶族自治县人民政府,是,否,否,,1,1,1
+广西来宾市民政局,广西来宾市民政局,否,是,否,,1,1,1
+广西莲诺工程管理有限公司,广西莲诺工程管理有限公司,否,是,否,,1,1,1
+广西民族大学采购服务网,广西民族大学采购服务网,否,是,是(部分栏目需登录),,1,1,0
+广西招标网,广西招标网,否,否,否,,1,1,1
+广西壮族自治区公共资源交易中心,广西壮族自治区公共资源交易中心,是,是,否,,1,1,1
+广西壮族自治区烟草专卖局,广西壮族自治区烟草专卖局,否,是,否,,1,1,1
+广西壮族自治区医疗保障局,广西壮族自治区医疗保障局,否,是,否,,1,1,1
+云南政府采购云平台,广西壮族自治区政府采购电子卖场,是,云南省部分数据,否,,1,1,1
+广西政府采购网,广西壮族自治区政府采购网,是,是,否,,1,1,1
+广西壮族自治区政府采购网,广西壮族自治区政府采购网,是,是,否,,1,1,1
+广州发展集团股份有限公司电子采购平台,广州发展电子采购平台,否,是,否,,1,1,1
+广州高新工程顾问有限公司,广州高新工程顾问有限公司,否,是,否,,1,1,1
+广州国企阳光采购服务平台,广州国企阳光采购服务平台,否,是,否,,1,1,1
+广州国企阳光采购信息发布平台,广州国企阳光采购信息发布平台,否,是,否,,1,1,1
+广州和稻丰农业科技发展有限公司,广州和稻丰农业科技发展有限公司,否,是,否,,1,0,
+广州民航职业技术学院,广州民航职业技术学院,否,是,否,,1,1,1
+广州群生招标代理有限公司,广州群生招标代理有限公司,否,是,否,,1,1,1
+广州市国科招标代理有限公司,广州市国科招标代理有限责任公司,否,是,否,,1,1,1
+广州市黄埔区人民政府,广州市黄埔区人民政府门户网站,是,是,否,,1,1,1
+广州市生态环境局,广州市生态环境局,否,是,否,,1,1,1
+广州市市场监督管理局,广州市市场监督管理局,否,是,否,,1,0,
+广州市增城区农村集体三资管理服务平台,广州市增城区农村集体三资管理服务平台,否,,,,1,1,1
+广州市政府采购平台,广州市政府采购中心,是,网站打不开,,,1,1,1
+广州市中级人民法院,广州市中级人民法院,否,是,否,,1,1,1
+广州医科大学附属第四医院,广州医科大学附属第四医院,否,是,否,,1,1,1
+广州银行,广州银行,否,是,否,,1,1,1
+广州中经招标有限公司,广州中经招标有限公司,否,否,否,,1,1,1
+广咨电子招投标交易平台,广咨电子招投标交易平台,否,否,否,,1,1,1
+贵州省公共资源交易中心,贵州省公共资源交易中心,是,是,否,,1,1,1
+贵州省招标投标公共服务平台,贵州省招标投标公共服务平台,是,是,否,,1,1,1
+贵州省政府采购网,贵州省政府采购网,是,是,否,,1,1,1
+贵州政府采购电子卖场,贵州省政府采购云平台,是,是,否,,1,1,1
+桂林市七星区人民政府,桂林市七星区人民政府,是,是,否,,1,1,1
+国e平台,国e平台,否,是,否,,1,1,1
+国采全流程电子化交易平台,国采全流程电子化交易平台,否,是,否,,1,1,1
+国家电力有限公司电子商务平台,国家电网公司电子商务平台,否,否,否,,1,1,1
+国家电网电子商务平台,国家电网公司电子商务平台,否,是,否,,1,1,1
+国投集团电子采购平台,国家开发投资公司(国投集团)电子采购平台,否,是,否,,1,1,1
+国家能源e购,国家能源e购,否,否,否,,1,1,1
+国家能源招标网,国家能源招标网,否,是,否,,1,1,1
+国家能源招标网(国家能源集团),国家能源招标网,否,是,否,,1,1,1
+国家税务总局吉林省税务局,国家税务总局吉林省税务局,否,是,否,,1,1,1
+国家税务总局江西省税务局,国家税务总局江西省税务局,否,是,否,,1,1,1
+国家税务总局深圳市税务局,国家税务总局深圳市税务局,否,是,否,,1,1,1
+国家烟草专卖局,国家烟草专卖局,否,无标讯数据,,,1,1,1
+国铁采购平台,国铁采购平台,否,是,否,,1,1,1
+国网山东省电力公司,国网山东省电力公司,否,是,否,,1,1,1
+国义招标股份有限公司,国义招标股份有限公司,否,是,否,,1,1,1
+青海省公共资源交易服务平台,果洛州公共资源交易网,是,是,否,,1,1,1
+哈尔滨市公共资源交易中心,哈尔滨市公共资源交易网,是,是,否,,1,1,1
+海尔集团公司,海尔集团公司,否,无标讯数据,,,1,1,1
+海南开放大学,海南开放大学,否,是,否,,1,1,1
+海南省临高县人民政府,海南省临高县人民政府,是,否,否,,1,1,1
+海南省民族博物馆,海南省民族博物馆,否,是,否,,1,1,1
+海南省政府采购网,海南省政府采购网,是,是,否,,1,1,1
+海峡保险,海峡保险,否,是,否,,1,1,1
+海信集团有限公司,海信集团公司非生产物资采购管理平台,否,是,是,,1,1,1
+杭州师范大学附属医院,杭州师范大学附属医院,否,否,否,,1,1,1
+杭州市民卡管理有限公司,杭州市民卡管理有限公司,否,是,否,,1,1,1
+全国公共资源交易平台(安徽省 ·合肥市),合肥市政府采购中心,是,否,否,,1,1,1
+河北省政府服务管理办公室,河北省公共资源交易中心,是,是,否,,1,1,1
+河北省招标投标公共服务平台,河北省招标投标公共服务平台,是,是,否,,1,1,1
+河北省政府采购网,河北省政府采购网,是,是,否,,1,1,1
+河北省政府采购网上商城,河北省政府采购网上商城,是,是,否,,1,1,1
+中国河北政府采购网,河北省政府采购网唐山市,是,是,否,,1,1,1
+河南省公共资源交易中心,河南省公共资源交易中心,是,否,否,,1,1,1
+河南省政府采购网,河南省政府采购网,是,是,否,,1,1,1
+河南省政府采购网上商城,河南省政府采购网上商城,是,是,否,,1,1,1
+河源市耀轩工程咨询有限公司,河源市耀轩工程咨询有限公司,否,否,否,,1,1,1
+鹤壁市公共资源交易中心,鹤壁市公共资源交易中心,是,否,否,,1,1,1
+黑龙江省政府采购网,黑龙江省政府采购网,是,否,否,,1,1,1
+黑龙江易采招标投标平台,黑龙江易采招标投标平台,否,是,否,,1,1,1
+全国公共资源交易平台(湖南),衡阳市公共资源交易服务平台,是,否,否,,1,1,1
+衡阳市公共资源交易中心,衡阳市公共资源交易网,是,否,否,,1,1,1
+呼伦贝尔市发展和改革委员会,呼伦贝尔市发展和改革委员会,否,是,否,,1,1,1
+呼伦贝尔市公共资源交易中心,呼伦贝尔市公共资源交易网,是,是,否,,1,1,1
+湖北省公共资源交易电子服务系统,湖北省公共资源交易电子服务系统,是,是,否,,1,1,1
+湖北省政府采购网,湖北省政府采购网,是,否,否,,1,1,1
+湖北省政府采购网上商城,湖北省政府采购网上商城,是,否,否,,1,1,1
+湖南省公共资源交易服务平台,湖南省公共资源交易服务平台,是,否,否,,1,1,1
+湖南省政府采购电子卖场,湖南省政府采购电子卖场,是,否,否,,1,1,1
+湖南政采云电子卖场,湖南省政府采购电子卖场,是,否,否,,1,1,1
+湖南省政府采购网,湖南省政府采购网,是,否,否,,1,1,1
+衡阳市政府采购网,湖南省政府采购网,是,否,否,,1,1,1
+郴州市政府采购网,湖南省政府采购网,是,否,否,,1,1,1
+怀化市政府采购网,湖南省政府采购网,是,否,否,,1,1,1
+湖南省邵阳市政府采购网,湖南省政府采购网,是,否,否,,1,1,1
+湖南省永州市政府采购网,湖南省政府采购网,是,否,否,,1,1,1
+湖南省张家界市政府采购网,湖南省政府采购网,是,否,否,,1,1,1
+湖南省益阳市政府采购网,湖南省政府采购网,是,否,否,,1,1,1
+中国湖南政府采购网,湖南省政府采购网,是,否,否,,1,1,1
+湖州绿色集采平台,湖州绿色集采平台,否,否,否,,1,1,1
+湖州市仁皇工程咨询有限公司,湖州市仁皇工程咨询有限公司,否,是,否,,1,1,1
+湖州星兴工程咨询有限公司,湖州星兴工程咨询有限公司,否,是,否,,1,1,1
+华安保险采购网,华安财产保险股份有限公司,否,是,否,,1,0,
+华侨城电子招采平台,华侨城电子招采平台,否,否,否,,1,1,1
+华润集团守正电子招标平台,华润集团守正电子招标平台,否,是,否,,1,1,1
+怀化市公共资源交易中心,怀化市公共资源交易网,是,是,否,,1,1,1
+黄山市教育局,黄山市教育局,否,无标讯数据,,,1,1,1
+惠东县第二人民医院,惠东县第二人民医院,否,是,否,,1,1,1
+惠阳区中医医院,惠阳区中医医院,否,是,否,,1,1,1
+惠州市博罗县人民政府网,惠州市博罗县人民政府网,是,是,否,,1,1,1
+惠州市公共资源交易中心,惠州市公共资源交易中心,是,是,否,,1,1,1
+惠州市农业农村局,惠州市农业农村局,否,是,否,,1,1,1
+机电产品招标投标电子交易平台,机电产品招标投标电子交易平台,否,否,是(竞品网站),,1,1,2
+吉林木学白求恩第二医院,吉林大学第二医院,否,是,否,,1,1,1
+吉林大学直采平台,吉林大学直采平台,否,是,否,,1,1,1
+吉林木学白求恩第三医院,吉林大学中日联谊医院,否,是,否,,1,1,1
+吉林省公共资源交易公共服务平台,吉林省公共资源交易公共服务平台,是,否,否,,1,1,1
+吉林省农村产权交易市场,吉林省农村产权交易市场,否,是,否,,1,1,1
+吉林省人民政府,吉林省人民政府,是,否,否,,1,1,1
+吉林省政府采购网,吉林省政府采购网,是,否,否,,1,1,1
+吉林省政府采购云平台,吉林省政府采购云平台,是,是,否,,1,1,1
+吉林省公共资源交易中心,吉林省政府采购中心,是,是,否,,1,1,1
+吉林市公共资源交易网,吉林市公共资源交易网,是,否,否,,1,1,1
+吉林医药学院采购与招投标管理中心,吉林医药学院采购与招投标管理中心,否,是,否,,1,1,1
+济南公共资源交易中心,济南公共资源交易中心,是,否,否,,1,1,1
+济南轨道交通集团有限公司,济南轨道交通集团有限公司,否,是,否,,1,1,1
+济南建招工程咨询有限公司,济南建招工程咨询有限公司,否,是,否,,1,1,1
+济南市政府采购网,济南市政府采购网,是,无新数据,,,1,0,
+济宁能源发展集团有限公司,济宁能源发展集团有限公司,否,近两年无数据发布,,,1,0,
+济宁市公共资源交易网,济宁市公共资源交易网,是,网站当前打不开,,,1,1,1
+鲁丽集团有限公司,冀中能源集团电子物资采购平台,否,是,否,,1,1,1
+山东泰山钢铁集团有限公司,冀中能源集团电子物资采购平台,否,是,否,,1,1,1
+嘉兴禾采联综合采购服务平台,嘉兴禾采联综合采购服务平台,否,否,否,,1,1,1
+嘉兴银行,嘉兴银行,否,是,否,,1,1,1
+江门市公共资源交易中心,江门公共资源交易网,是,是,否,,1,1,1
+江门市采购行业协会,江门市采购协会,否,是,否,,1,1,1
+江门市人民政府,江门市人民政府,是,否,否,,1,1,1
+江苏畅誉项目管理有限公司,江苏畅誉项目管理有限公司,否,是,否,,1,1,1
+江苏春为全过程工程咨询有限公司,江苏春为全过程工程咨询有限公司,否,是,否,,1,1,1
+江苏大学采购与招标办公室,江苏大学采购与招标办公室,否,是,否,,1,1,1
+江苏建博工程管理咨询有限公司,江苏建博工程管理咨询有限公司,否,是,否,,1,1,1
+江苏句容农村商业银行,江苏句容农村商业银行,否,是,否,,1,1,1
+江苏乐奇信息技术有限公司,江苏乐奇信息技术有限公司,否,域名失效,网站作废,,,1,1,1
+江苏省公共资源交易平台,江苏省公共资源交易平台,是,是,否,,1,1,1
+江苏省姜堰中等专业学校,江苏省姜堰中等专业学校,否,是,否,,1,0,
+江苏省招标投标公共服务平台,江苏省招标投标公共服务平台,是,否,否,,1,1,1
+江苏省政府采购网,江苏省政府采购网,是,是,否,,1,1,1
+江苏沭阳农村商业银行,江苏沭阳农村商业银行,否,是,否,,1,1,1
+江苏苏瑾创招标代理有限公司,江苏苏瑾创招标代理有限公司,否,是,否,,1,1,1
+江苏泰州市姜堰区人民法院,江苏泰州市姜堰区人民法院,否,是,否,,1,0,
+江苏武晋工程咨询有限公司,江苏武晋工程咨询有限公司,否,是,否,,1,1,1
+江苏鑫洋土地房地产评估有限公司,江苏鑫洋土地房地产评估有限公司,否,是,否,,1,1,1
+江苏艺程建设工程有限公司,江苏艺程建设工程有限公司,否,是,否,,1,1,1
+江西衡正招投标技术咨询有限公司,江西衡正招投标技术咨询有限公司,否,否,否,,1,1,1
+江西省安标工程项目管理有限公司,江西省安标工程项目管理有限公司,否,是,否,,1,1,1
+江西省公共资源交易网,江西省公共资源交易网,是,否,否,,1,1,1
+江西省人民政府网,江西省人民政府网,是,否,否,,1,1,1
+江西省政府采购网,江西省政府采购网,是,是,否,,1,1,1
+交安汇,交安汇,否,是,是(部分数据需会员登录),,1,1,0
+焦作市公共资源交易中心,焦作市公共资源交易中心,是,是,否,,1,1,1
+解放号软件产业互联网平台,解放号软件产业互联网平台,否,数据均为转载三方网站数据,,,1,1,1
+金采网,金采网,否,是,是(已有账号),,1,1,1
+金华市交通投资集团有限公司,金华市交通投资集团有限公司,否,是,否,,1,1,1
+金隅冀东阳光采购平台,金隅冀东阳光采购平台,否,网站当前打不开,,,1,1,1
+警务招标网,警务招标网,否,否,是(部分栏目需登录),,1,1,0
+句容市人民法院,句容市人民法院,否,否,否,,1,1,1
+军队采购网,军队采购网,是,是,否,,1,1,1
+军队采购网(中央军委后勤保障部),军队采购网,否,是,否,,1,1,1
+军队网,军队采购网,否,是,否,,1,1,1
+开封市公共资源交易中心,开封市公共资源交易中心,是,是,否,,1,1,1
+济南第二公共资源交易中心,莱芜市公共资源交易网,是,是,否,,1,1,1
+莱芜市政府采购网,莱芜市政府采购网,是,,,,1,1,1
+郎溪县人民政府,郎溪县人民政府,是,否,否,,1,1,1
+崂山区人民政府,崂山区人民政府,是,是,否,,1,1,1
+丽水市阳光采购服务平台,丽水市阳光采购服务平台,否,否,否,,1,1,1
+利华益集团股份有限公司,利华益集团,否,否,否,,1,1,1
+连云港经济技术开发区管理委员会,连云港经济技术开发区管理委员会,否,是,否,,1,1,1
+连云港市赣榆区住房和城乡建设局,连云港市赣榆区住房和城乡建设局,否,是,否,,1,1,1
+凉山州发展(控股)集团有限责任公司,凉山州发展集团有限责任公司,否,是,否,,1,1,1
+凉山州公共资源交易服务中心,凉山州公共资源交易服务中心,是,是,否,,1,1,1
+辽宁省公共资源交易网,辽宁省公共资源交易中心,是,是,否,,1,1,1
+辽宁省血液中心,辽宁省血液中心,否,是,否,,1,1,1
+辽宁省政府采购网,辽宁省政府采购网,是,是,否,,1,1,1
+辽宁省网上商城,辽宁政府采购网,是,是,否,,1,1,1
+辽源市公共资源交易服务网,辽源市公共资源交易服务网,是,是,否,,1,1,1
+聊城市第二人民医院官方网站,聊城市第二人民医院,否,是,否,,1,1,1
+聊城市公共资源交易网,聊城市公共资源交易网,是,网站打不开,,,1,1,1
+聊城市政府采购信息网,聊城市政府采购网,是,网站打不开,,,1,1,1
+聊城市政府采购网上商城,聊城市政府采购网上商城,是,网站打不开,,,1,1,1
+临沂政务服务公共资源交易网,临沂市公共资源交易中心,是,是,否,,1,1,1
+临沂市公共资源交易中心,临沂市公共资源交易中心,否,是,否,,1,1,1
+临沂市阳光采购服务平台,临沂市阳光采购服务平台,否,否,否,,1,1,1
+临沂市政府采购网,临沂市政府采购网,是,网站打不开,,,1,1,1
+山东玲珑轮胎股份有限公司,玲珑轮胎,否,是,否,,1,1,1
+柳州市交通学校,柳州市交通学校,否,是,否,,1,1,1
+柳州市中医医院,柳州市中医医院,否,是,否,,1,1,1
+六盘水市住房公积金管理中心,六盘水市住房公积金管理中心,否,是,否,,1,0,
+龙岩市公共资源交易中心,龙岩市公共资源交易中心,是,否,否,,1,1,1
+娄底市公共资源交易中心,娄底市公共资源交易中心,是,是,否,,1,1,1
+泸州市公安局,泸州市公安局,否,是,否,,1,1,1
+山东鲁花集团有限公司,鲁花集团电子采购平台,否,是,是(已有账号),,1,1,1
+鲁西化工集团股份有限公司,鲁西化工集团股份有限公司,否,否,否,,1,1,1
+洛阳市公共资源交易中心,洛阳市公共资源交易中心,是,否,否,,1,1,1
+漯河市公共资源交易中心,漯河市公共资源交易信息网,是,否,否,,1,1,1
+漯河市生态环境局,漯河市生态环境局,否,是,否,,1,1,1
+南方招标与采购交易平台,南方招标与采购交易平台,否,是,否,,1,1,1
+南京市农村产权交易信息服务平台,南京市农村产权交易信息服务平台,否,是,否,,1,1,1
+南山集团有限公司,南山集团有限公司,否,是,否,,1,1,1
+南通大学招标管理办公室,南通大学招标管理办公室,否,是,否,,1,1,1
+南通港港口集团有限公司,南通港港口集团有限公司,否,是,否,,1,1,1
+南通农商银行,南通农商银行,否,是,否,,1,1,1
+南通市崇川区人民政府网,南通市崇川区人民政府网,是,是,否,,1,1,1
+南通市海门区人民政府,南通市海门区人民政府,是,否,否,,1,1,1
+南通市人民政府,南通市人民政府,是,是,否,,1,1,1
+南通市如皋市政府采购网上商城,南通市如皋市政府采购网上商城,是,平台停止运营,,,1,1,1
+南通市中级人民法院,南通市中级人民法院,否,是,否,,1,1,1
+南通市中央创新区建设投资有限公司,南通市中央创新区建设投资有限公司,否,是,否,,1,1,1
+南通市中医院,南通市中医院,否,是,否,,1,1,1
+南阳市公共资源交易中心,南阳市宛城区公共资源交易中心,是,是,否,,1,0,
+内江市国有企业阳光采购服务平台,内江市国有企业阳光采购服务平台,否,是,否,,1,1,1
+内蒙古和林格尔新区,内蒙古和林格尔新区,否,否,否,,1,1,1
+内蒙古自治区公共资源交易网,内蒙古自治区公共资源交易网,是,否,否,,1,1,1
+内蒙古政府采购电子卖场,内蒙古自治区政府采购电子卖场,是,是,否,,1,1,1
+内蒙古自治区政府采购网,内蒙古自治区政府采购网,是,是,否,,1,1,1
+宁波市鄞州人民医院,宁波市鄞州人民医院,否,是,否,,1,1,1
+宁波市镇海区人民政府,宁波市镇海区人民政府,是,是,否,,1,1,1
+宁海县妇幼保健院,宁海县妇幼保健院,否,是,否,,1,1,1
+宁夏回族自治区公共资源交易网,宁夏回族自治区公共资源交易网,是,是,否,,1,1,1
+宁夏公共资源交易网,宁夏回族自治区公共资源交易网,是,是,否,,1,1,1
+宁夏回族自治区政府采购网,宁夏政府采购公共服务平台,是,否,否,,1,1,1
+攀枝花钢城集团电子招标采购管理平台,攀枝花钢城集团电子招标采购管理平台,否,是,否,,1,1,1
+攀枝花市公共资源交易中心,攀枝花市公共资源交易服务中心,是,否,是,,1,1,1
+平顶山市公共资源交易中心,平顶山市公共资源交易中心,是,否,否,,1,1,1
+平凉市公共资源交易网新网址,平凉市公共资源交易网新网址,是,否,否,,1,1,1
+莆田市教育局,莆田市教育局,否,是,否,,1,1,1
+莆田学院附属医院,莆田学院附属医院,否,是,否,,1,1,1
+濮阳市公共资源交易中心,濮阳市公共资源交易平台,是,否,否,,1,1,1
+齐鲁制药有限公司,齐鲁制药,否,是,否,,1,1,1
+黔西南州公共资源交易中心,黔西南州公共资源交易中心,是,否,否,,1,1,1
+秦皇岛市公共资源交易网,秦皇岛市公共资源交易网,是,是,否,,1,1,1
+秦皇岛市公共资源交易中心,秦皇岛市公共资源交易网,是,是,否,,1,1,1
+青岛啤酒集团有限公司,青岛啤酒集团有限公司,否,,,,1,1,1
+青岛市公共资源交易电子服务系统,青岛市公共资源交易电子服务系统,否,否,否,,1,1,1
+青岛市广播电视台采购与招标网,青岛市广播电视台采购与招标网,否,是,否,,1,1,1
+青岛市政府采购网,青岛市政府采购网,是,网站打不开,,,1,1,1
+青海省公共资源交易网,青海省公共资源交易网,是,是,否,,1,1,1
+青海省卫生健康委员会,青海省卫生健康委员会,否,是,否,,1,1,1
+青海省政府采购网,青海政府采购,是,否,否,,1,1,1
+邛崃市第二人民医院,邛崃市第二人民医院,否,否,否,,1,1,1
+衢州市常山县人民政府网,衢州市常山县人民政府网,是,否,否,,1,1,1
+全国公共资源交易平台,全国公共资源交易平台,是,是,否,,1,1,1
+全国招投标资源交易平台,全国招投标资源交易平台,是,是,否,,1,1,1
+全军武器装备采购信息网,全军武器装备采购信息网,否,是,是(已有账号),,1,1,1
+泉州国资阳光集中采购平台,泉州国资阳光集中采购平台,否,是,否,,1,1,1
+日照钢铁控股集团有限公司,日照钢铁控股集团有限公司,否,,,,1,1,1
+日照市公共资源交易网,日照市公共资源交易网,是,网站打不开,,,1,1,1
+如东限额交易网,如东限额交易网,否,是,否,,1,1,1
+润启招投标,润启招投标,否,是,否,,1,0,
+三门峡市公共资源交易中心,三门峡市公共资源交易中心,是,否,否,,1,1,1
+全国公共资源交易平台(海南省),三亚市政务中心公共资源交易网,是,是,否,,1,1,1
+海南省公共资源交易服务中心,三亚市政务中心公共资源交易网,是,是,否,,1,1,1
+山东博汇纸业股份有限公司,山东博汇纸业股份有限公司,否,,,,1,1,1
+晨鸣控股有限公司,山东晨鸣纸业集团股份有限公司,否,是,否,,1,0,
+山东创新金属科技有限公司,山东创新集团电子采购平台,否,是,否,,1,1,1
+山东钢铁集团有限公司,山东钢铁集团有限公司,否,否,否,,1,1,1
+山东钢铁集团有限公司招标采购与拍卖管理信息平台,山东钢铁集团有限公司招标采购与拍卖管理信息平台,否,否,否,,1,1,1
+山东钢铁集团日照有限公司,山东钢铁集团有限公司招标采购与拍卖管理信息平台,否,否,否,,1,1,1
+山东省港口集团滨州港有限公司,山东港口阳光慧采e平台,否,否,否,,1,1,1
+山东省港口集团东营港有限公司,山东港口阳光慧采e平台,否,否,否,,1,1,1
+山东港口陆海国际物流集团有限公司,山东港口阳光慧采e平台,否,否,否,,1,1,1
+山东港湾建设集团有限公司临沂分公司,山东港口阳光慧采e平台,否,否,否,,1,1,1
+山东省港口集团有限公司,山东港口阳光慧采e平台,否,否,否,,1,1,1
+山东港口日照港集团有限公司,山东港口阳光慧采e平台,否,否,否,,1,1,1
+山东港湾建设集团有限公司威海分公司,山东港口阳光慧采e平台,否,否,否,,1,1,1
+山东省港口集团潍坊港有限公司,山东港口阳光慧采e平台,否,否,否,,1,1,1
+山东港口烟台港集团有限公司,山东港口阳光慧采e平台,否,否,否,,1,1,1
+山东高速集团有限公司,山东高速集团有限公司,否,是,否,,1,1,1
+山东核电有限公司,山东核电有限公司,否,否,否,,1,0,
+山东恒邦冶炼股份有限公司,山东恒邦冶炼股份有限公司,否,无标讯数据,,,1,0,
+山东华标招标有限公司,山东华标招标有限公司,否,是,否,,1,1,1
+山东黄金集团有限公司,山东黄金集团有限公司,否,是,否,,1,0,
+山东金岭集团有限公司,山东金岭集团有限公司,否,是,否,,1,1,1
+山东九羊集团有限公司,山东九羊集团有限公司,否,否,否,,1,1,1
+山东鲁抗医药股份有限公司,山东鲁抗医药股份有限公司,否,是,否,,1,1,1
+东鲁投招标有限公司网站,山东鲁投招标有限公司,否,否,否,,1,1,1
+山东能源集团在线询比价平台,山东能源集团在线询比价平台,否,是,否,,1,0,
+山东普华项目管理有限公司,山东普华项目管理有限公司,否,是,否,,1,1,1
+山东日照政府采购网,山东日照政府采购网,是,域名失效,,,1,1,1
+山东省采购与招标网,山东省采购与招标网,是,该站点爬虫全部下架,是(已有账号,账号被冻结),,1,1,0
+山东省公共资源交易网,山东省公共资源交易网,是,是,否,,1,1,1
+山东鲁成招标有限公司,山东省鲁成招标有限公司,否,是,否,,1,1,1
+山东省农村信用社联合社,山东省农村信用社联合社,否,是,否,,1,1,1
+山东省商业集团有限公司,山东省商业集团有限公司,否,否,否,,1,1,1
+山东省水利工程招标投标公共服务平台,山东省水利工程招标投标公共服务平台,是,否,否,,1,1,1
+山东省政府采购网上商城新版,山东省政府采购网上商城新版,是,否,否,,1,1,1
+山东盛和招标代理有限公司,山东盛和招标代理有限公司,否,是,否,,1,1,1
+山东魏桥创业集团有限公司,山东魏桥创业集团有限公司,否,是,否,,1,1,1
+山东裕龙石化有限公司,山东裕龙石化有限公司,否,是,否,,1,1,1
+山东招标股份有限公司,山东招标股份有限公司,否,否,否,,1,1,1
+山东政府集中采购网,山东政府集中采购网,是,域名失效,,,1,1,1
+山东重工集团有限公司,山东重工集团有限公司,否,无标讯数据,,,1,1,1
+莱芜钢铁集团有限公司,山钢股份莱芜分公司电子交易平台,否,网站打不开,,,1,1,1
+山推工程机械股份有限公司,山推工程机械股份有限公司,否,是,否,,1,1,1
+山西省公共资源交易平台,山西省公共资源交易平台,是,是,否,,1,1,1
+山西省政府采购电子卖场,山西省政府采购电子卖场,是,是,否,,1,1,1
+陕西采购与招标网,陕西采购与招标网,否,是,否,,1,1,1
+陕西能源职业技术学院,陕西能源职业技术学院,否,是,否,,1,1,1
+陕西秦农农村商业银行股份有限公司,陕西秦农农村商业银行股份有限公司,否,是,否,,1,1,1
+陕西省公共资源交易中心,陕西省公共资源交易中心,是,是,否,,1,1,1
+陕西省人民医院,陕西省人民医院,否,是,否,,1,1,1
+陕西省政府采购网,陕西省政府采购网,是,是,否,,1,1,1
+汕头大学,汕头大学,否,是,否,,1,1,1
+汕头大学医学院第二附属医院,汕头大学医学院第二附属医院,否,是,否,,1,1,1
+汕头市潮阳区集体资产资源交易平台,汕头市潮阳区集体资产资源交易平台,否,是,否,,1,1,1
+汕头市人民政府,汕头市发展和改革局,是,是,否,,1,0,
+汕尾市公共资源交易中心,汕尾市公共资源交易网,是,否,否,,1,1,1
+商丘市公共资源交易中心,商丘市公共资源交易服务平台,是,是,否,,1,1,1
+上蔡县人民政府,上蔡县人民政府,是,是,否,,1,1,1
+上海市材料工程学校,上海市材料工程学校,否,是,否,,1,1,1
+上海市公共资源交易网,上海市公共资源交易中心,是,是,否,,1,1,1
+上海信托,上海信托,否,是,否,,1,1,1
+上海应用技术大学信息公开网,上海应用技术大学信息公开网,否,否,否,,1,1,1
+上海政府采购网,上海政府采购网,是,是,否,,1,1,1
+上海市政府采购网,上海政府采购网,是,是,否,,1,1,1
+上海政府采购网上超市,上海政府采购云平台,是,是,否,,1,1,1
+韶关市人民政府,韶关市人民政府,是,否,否,,1,1,1
+韶关市网上中介服务超市,韶关市网上中介超市,否,网站打不开,,,1,1,1
+韶关市文化广电旅游体育局,韶关市文化广电旅游体育局,否,是,否,,1,1,1
+韶关招标采购网,韶关招标采购网,否,是,否,,1,1,1
+绍兴公共资源交易网,绍兴市公共资源交易网,是,是,否,,1,1,1
+绍兴市越城区人民政府网,绍兴市越城区人民政府网,是,否,否,,1,1,1
+绍兴文理学院招投标与采购中心,绍兴文理学院招投标与采购中心,否,是,否,,1,1,1
+射阳县中医院,射阳县中医院,否,否,否,,1,1,1
+深圳市民政局,深圳民政在线,否,是,否,,1,1,1
+深圳前海合作区人民法院,深圳前海合作区人民法院,否,是,否,,1,1,1
+深圳市地方金融监督管理局(深圳市人民政府金融工作办公室),深圳市地方金融监督管理局,是,是,否,,1,1,1
+深圳市规划和自然资源局,深圳市规划和自然资源局,否,否,否,,1,1,1
+深圳市国际招标有限公司,深圳市国际招标有限公司,否,是,否,,1,1,1
+深圳市国信招标有限公司,深圳市国信招标有限公司,否,是,否,,1,0,
+龙岗政府在线,深圳市龙岗区教育局,是,是,否,,1,1,1
+深圳公共资源交易中心龙华分公司,深圳市龙华区公共资源交易中心,是,域名失效,网站作废,,,1,1,1
+龙华区教育局,深圳市龙华区教育局,否,是,否,,1,1,1
+深圳市人大常委会,深圳市人大常委会,否,是,否,,1,1,1
+深圳市人民医院,深圳市人民医院,否,是,否,,1,1,1
+深圳政府在线,深圳市人民政府,是,是,否,,1,1,1
+深圳市司法局,深圳市司法局,否,是,否,,1,1,1
+深圳市退役军人事务局,深圳市退役军人事务局,否,否,否,,1,1,1
+深圳市卫生健康委员会,深圳市卫生健康委员会,否,否,否,,1,1,1
+深圳市文化广电旅游体育局,深圳市文化广电旅游体育局,否,是,否,,1,1,1
+深圳市振东招标代理有限公司,深圳市振东招标代理有限公司,否,是,否,,1,1,1
+深圳公共资源交易中心,深圳市政府采购监管网,是,是,否,,1,1,1
+深圳阳光采购平台,深圳阳光采购平台,否,是,否,,1,1,1
+深圳证券交易所,深圳证券交易所,否,是,否,,1,1,1
+深圳中邦国际工程科技顾问有限公司,深圳中邦国际工程科技顾问有限公司,否,是,否,,1,1,1
+十环招标网,十环招标网,否,否,否,,1,1,1
+石横特钢集团有限公司,石横特钢采购电商平台,否,是,否,,1,1,1
+全国公共资源交易平台(山西省 ·朔州市)朔州市营商环境促进中心,朔州市公共资源交易网,是,否,否,,1,1,1
+朔州市公共资源交易平台,朔州市公共资源交易网,是,否,否,,1,1,1
+四川广电网络集团,四川广电网络集团,否,无数据,,,1,1,1
+四川省公共资源交易信息网,四川省公共资源交易服务平台,是,是,否,,1,1,1
+四川省肿瘤医院,四川省肿瘤医院,否,是,否,,1,1,1
+四川轩辕招标代理有限公司,四川轩辕招标代理有限公司,否,是,否,,1,1,1
+四川政府采购网,四川政府采购,是,是,否,,1,1,1
+四川省政府采购网,四川政府采购,是,是,否,,1,1,1
+四川政府采购一体化平台,四川政府采购,是,是,否,,1,1,1
+四平市公共资源交易中心,四平市公共资源交易中心,是,是,否,,1,1,1
+泗县人民政府,泗县人民政府,是,是,否,,1,1,1
+松原市公共资源交易中心,松原市公共资源交易中心,是,是,否,,1,1,1
+苏州工业职业技术学院后勤与资产管理处,苏州工业职业技术学院后勤与资产管理处,否,是,否,,1,1,1
+苏州涵熙工程建设咨询有限公司,苏州涵熙工程建设咨询有限公司,否,是,否,,1,1,1
+苏州市公共资源交易中心,苏州市公共资源交易中心,是,否,否,,1,1,1
+苏州市原鑫招投标咨询服务有限公司,苏州市原鑫招投标咨询服务有限公司,否,是,否,,1,1,1
+苏州筑合工程咨询有限公司,苏州筑合工程咨询有限公司,否,是,否,,1,1,1
+宿迁市财政局,宿迁市财政局,否,是,否,,1,1,1
+宿迁市楚润数据集团有限公司,宿迁市楚润数据集团有限公司,否,是,否,,1,1,1
+宿迁市老年医院,宿迁市老年医院,否,是,否,,1,1,1
+宿迁市农村产权交易信息服务平台,宿迁市农村产权交易信息服务平台,否,是,否,,1,1,1
+宿迁市司法局,宿迁市司法局,否,是,否,,1,0,
+宿迁市退役军人事务局,宿迁市退役军人事务局,否,是,否,,1,1,1
+宿州市司法局,宿州市司法局,否,是,否,,1,0,
+太平洋保险采购电子化管理平台,太平洋保险,否,是,否,,1,1,1
+泰安市公共资源交易网,泰安市公共资源交易网,是,否,否,,1,1,1
+泰开集团有限公司,泰开电子采购平台,否,是,是(部门栏目需登录,账号用户名或密码错误),,1,1,0
+泰兴市人民政府,泰兴市人民政府,是,是,否,,1,1,1
+泰州市农村产权交易信息服务平台,泰州市农村产权交易信息服务平台,否,是,否,,1,1,1
+泰州唯一视听门户网,泰州唯一视听门户网,否,是,否,,1,0,
+滕州市妇幼保院官网,滕州市妇幼保健院,否,是,否,,1,1,1
+天津能源集团电子商务平台,天津能源集团电子商务平台,否,是,否,,1,1,1
+天津市公共资源交易网,天津市公共资源交易网,是,是,否,,1,1,1
+天津市交通运输委员会,天津市交通运输委员会,否,是,否,,1,1,1
+天津市政府采购网,天津市政府采购网,是,是,否,,1,1,1
+天津市政府采购中心,天津市政府采购中心,是,是,否,,1,1,1
+公共采购云平台,天津市政府采购中心电子卖场,否,是,否,,1,1,1
+天威视讯,天威视讯,否,是,否,,1,1,1
+铁建汇采工程物资设备电商平台,铁建汇采工程物资设备电商平台,否,是,否,,1,1,1
+通化市公共资源交易中心,通化市公共资源交易网,是,是,否,,1,0,
+通辽市公共资源交易中心,通辽市公共资源交易中心,是,网站链接打不开,,,1,1,1
+通州湾江海联动开发示范区,通州湾江海联动开发示范区,否,是,否,,1,1,1
+万华化学集团股份有限公司,万华化学集团股份有限公司,否,是,否,,1,1,1
+威海市公共资源交易网,威海市公共资源交易网,是,是,否,,1,1,1
+威海市建设工程电子交易系统,威海市建设工程电子交易系统,否,是,否,,1,1,1
+潍柴控股集团有限公司,潍柴控股集团有限公司,否,是,否,,1,1,1
+潍坊市公共资源交易中心,潍坊市公共资源交易中心,是,是,否,,1,1,1
+潍坊市政府采购网,潍坊市政府采购网,是,站点已作废,,,1,1,1
+潍坊特钢集团有限公司,潍坊特钢集团有限公司,否,网站打不开,,,1,0,
+乌海市公共资源交易中心,乌海市公共资源交易中心,是,内蒙古自治区公共资源交易网已收录,,,1,1,1
+乌鲁木齐采购网,乌鲁木齐市政府采购中心,否,是,否,,1,1,1
+无锡市公安局,无锡市公安局,否,是,否,,1,1,1
+无锡市新吴区人民政府网,无锡市新吴区人民政府网,是,是,否,,1,1,1
+梧州市红十字会医院,梧州市红十字会医院,否,是,否,,1,1,1
+五粮液电子招标采购平台,五粮液电子招标采购平台,否,是,否,,1,1,1
+西藏自治区政府采购网,西藏自治区政府采购网,是,是,否,,1,1,1
+西藏自治区政府采购网上商城,西藏自治区政府采购网上商城,是,网页链接打不开,,,1,0,
+西宁市公共资源交易网,西宁市公共资源交易网,是,部分栏目由站点青海省公共资源交易网收录,否,,1,1,1
+内蒙古公共资源交易管理服务中心,锡林郭勒盟公共资源交易,是,否,否,,1,1,1
+咸宁市公共资源电子交易平台,咸宁市公共资源电子交易平台,是,否,否,,1,1,1
+香港城市大学(东莞),香港城市大学(东莞),否,是,否,,1,1,1
+湘潭市公共资源交易中心,湘潭市公共资源交易中心,是,是,否,,1,1,1
+祥云县人民医院,祥云县人民医院,否,是,否,,1,1,1
+新疆公共资源交易网,新疆公共资源交易网,是,是,否,,1,1,1
+新疆生产建设兵团公共资源交易信息网,新疆生产建设兵团公共资源交易,是,否,否,,1,1,1
+新疆维吾尔自治区政府采购网,新疆维吾尔自治区政府采购网,是,是,否,,1,1,1
+新疆政府采购网,新疆维吾尔自治区政府采购中心,是,是,否,,1,1,1
+新乡市公共资源交易中心,新乡市公共资源交易中心,是,是,否,,1,1,1
+新乡市疾病预防控制中心,新乡市疾病预防控制中心,否,是,否,,1,0,
+无棣鑫岳化工集团有限公司,鑫岳集团,否,是,否,,1,1,1
+信阳市公共资源交易中心,信阳市新县公共资源交易平台,是,否,否,,1,1,1
+邢台市公共资源交易网,邢台市公共资源交易网,是,是,否,,1,1,1
+秀洲区小型工程电子交易平台,秀洲区小型工程电子交易平台,否,是,否,,1,1,1
+盱眙县人民医院,盱眙县人民医院,否,是,否,,1,1,1
+徐圩新区公共资源交易平台,徐圩新区非招标采购电子实施平台,是,是,否,,1,1,1
+许昌市公共资源交易中心,许昌市公共资源交易中心,是,是,否,,1,1,1
+宣城市市场监督管理局,宣城市市场监督管理局,否,是,否,,1,1,1
+美云智数寻源云,寻源云,否,是,否,,1,1,1
+全国公共资源交易平台(四川省 雅安市),雅安市公共资源交易服务中心,是,否,否,,1,1,1
+雅安市科学技术局,雅安市科学技术局,否,是,否,,1,0,
+雅安市人民医院,雅安市人民医院,否,是,否,,1,1,1
+烟草行业招投标信息平台,烟草行业招投标信息平台,否,网站打不开,,,1,1,1
+烟台市公共资源交易网,烟台市公共资源交易网,是,是,否,,1,1,1
+烟台泰和新材料股份有限公司,烟台市政府采购监督管理平台,否,是,否,,1,1,1
+烟台市政府采购网,烟台市政府采购网,是,是,否,,1,1,1
+延边朝鲜族自治州公共资源交易网,延边朝鲜族自治州公共资源交易网,是,是,否,,1,1,1
+盐城市人民政府,盐城市人民政府,是,是,否,,1,1,1
+盐城市盐都区人民政府,盐城市盐都区人民政府,是,否,否,,1,1,1
+扬州工业职业技术学院国有资产管理处,扬州工业职业技术学院国有资产管理处,否,是,否,,1,1,1
+扬州市公共资源交易中心,扬州市公共资源交易中心,是,是,否,,1,1,1
+扬州市公共资源交易中心开发区分中心,扬州市公共资源交易中心开发区分中心,是,该站点爬虫已作废,网站改版,,,1,1,1
+扬州市邗江区人民政府网,扬州市邗江区人民政府网,是,是,否,,1,1,1
+扬州市江都妇幼保健院,扬州市江都妇幼保健院,否,是,否,,1,1,1
+阳光采购服务平台,阳光采购服务平台,否,是,否,,1,1,1
+山东能源集团鲁西矿业有限公司,阳光采购服务平台,否,是,否,,1,1,1
+沂州集团有限公司,沂州集团,否,是,否,,1,1,1
+宜宾市公共资源交易信息网,宜宾市公共资源交易信息网,是,否,否,,1,1,1
+宜宾市屏山县人民政府网,宜宾市屏山县人民政府网,是,是,否,,1,1,1
+宜宾市企业“e路阳光 ”公共服务平台,宜宾市企业e路阳光公共服务平台,否,是,否,,1,1,1
+宜宾市公共资源交易信息网 建设工地场地信息,宜宾市企业e路阳光公共服务平台,是,是,否,,1,1,1
+宜宾市公共资源交易信息网 国企招标,宜宾市企业e路阳光公共服务平台,是,是,否,,1,1,1
+宜春学院招标采购中心,宜春学院招标采购中心,否,是,否,,1,1,1
+随行易交易电子招标投标交易平台,易交易电子招标投标交易平台,否,是,否,,1,1,1
+易能智招电子交易平台,易能智招电子交易平台,否,是,否,,1,1,1
+益阳市公共资源交易中心,益阳公共资源交易中心,是,是,否,,1,1,1
+益阳医学高等专科学校,益阳医学高等专科学校,否,是,否,,1,1,1
+赢标电子招标采购交易平台山西专区,赢标电子招标采购交易平台山西专区,否,是,否,,1,1,1
+永州市公共资源交易中心,永州市公共资源交易网,是,是,否,,1,1,1
+邮E招电子招投标交易平台,邮E招电子招投标交易平台,否,是,否,,1,1,1
+友云采,友云采,否,是,否,,1,1,1
+玉林市人民政府网,玉林市人民政府网,是,是,否,,1,1,1
+岳阳市公共资源交易中心,岳阳市公共资源交易中心,是,是,否,,1,1,1
+粤商通,粤商通,否,是,否,,1,1,1
+云采链(广州)信息科技有限公司,云采链线上采购一体化平台,否,是,否,,1,1,1
+云采通 高校采购联盟,云采通高校采购联盟,否,是,否,,1,1,1
+云浮市公共资源交易网,云浮市公共资源交易网,是,否,否,,1,1,1
+云南省公共资源交易信息网,云南省公共资源交易信息网,是,否,否,,1,1,1
+云南省政府采购网,云南省政府采购网,是,是,否,,1,1,1
+枣庄市公共资源交易网,枣庄市公共资源交易网,是,是,否,,1,1,1
+湛江市公共资源交易中心,湛江市公共资源交易中心,是,合并至省政府采购网,,,1,1,1
+湛江市鑫丰招标代理有限公司,湛江市鑫丰招标代理有限公司,否,是,否,,1,1,1
+张家界市公共资源交易中心,张家界市公共资源交易中心,是,是,否,,1,1,1
+长白山管委会公共资源交易信息网,长白山管委会公共资源交易信息网,是,是,否,,1,1,1
+大成集团,长春大成实业集团有限公司,否,是,否,,1,1,1
+长春市公共资源交易网,长春市公共资源交易网,是,是,否,,1,1,1
+长沙市殡葬事务中心,长沙市殡葬事务中心,否,是,否,,1,0,
+招采进宝通用专区,招采进宝通用专区,否,否,否,,1,1,1
+招商局集团电子招标采购交易平台,招商局集团电子招标采购交易平台,否,是,是(部分栏目需登录),,1,1,0
+招商银行采购管理平台,招商银行采购管理平台,否,是,否,,1,1,1
+肇庆市高要区交通运输局,肇庆市高要区交通运输局,否,是,否,,1,1,1
+浙江海港电子招标采购平台,浙江海港电子招标采购平台,否,否,否,,1,1,1
+浙江省公共资源交易服务平台,浙江省公共资源交易服务平台,是,否,否,,1,1,1
+浙江省数据管理有限公司,浙江省数据管理有限公司,否,是,否,,1,1,1
+浙江政府采购网,浙江政府采购网,是,是,否,,1,1,1
+镇好采服务类网上商城,镇好采服务类网上商城,否,网站变更,跳转至该站点,该站点已全部收录,,,1,1,1
+镇江农商银行,镇江农商银行,否,是,否,,1,0,
+镇江市农村产权交易信息服务平台,镇江市农村产权交易信息服务平台,否,是,否,,1,1,1
+郑州市公共资源交易中心,郑州市公共资源交易中心,是,是,否,,1,1,1
+政采云市场资源交易服务中心,政采云市场资源交易服务中心,否,是,否,,1,1,1
+政村企阳光招采平台,政村企阳光采购平台,否,是,否,,1,1,1
+政府采购频道,政府采购频道,是,是,否,,1,1,1
+政府采购云平台,政府采购云平台,是,是,否,,1,1,1
+中车山东机车车辆有限公司,中车山东机车车辆有限公司,否,是,否,,1,0,
+中达通采智慧云平台,中达通采智慧云平台,否,否,否,,1,1,1
+中共安庆市委统战部,中共安庆市委统战部,否,是,否,,1,1,1
+中共北京市委老干部局,中共北京市委老干部局,否,是,否,,1,1,1
+中共南通市委老干部局,中共南通市委老干部局,否,是,否,,1,1,1
+中广核电子商务平台,中广核电子商务平台,否,是,否,,1,1,1
+中国安能建设集团有限公司电子采购平台,中国安能建设集团有限公司电子采购平台,否,是,否,,1,1,1
+中国财经报,中国财经报网,否,是,否,,1,1,1
+中国财政报网,中国财经报网,否,是,否,,1,1,1
+中国大唐集团公司电子商务平台,中国大唐集团公司电子商务平台,否,是,否,,1,1,1
+大唐山东发电有限公司,中国大唐集团公司电子商务平台,否,是,否,,1,1,1
+中国大唐集团有限公司,中国大唐集团有限公司,否,无标讯数据,,,1,1,1
+中国电力设备信息网,中国电力设备信息网,否,是,否,,1,1,1
+中国电子科技集团电子采购平台,中国电子科技集团有限公司电子采购平台,否,是,是(已有账号),,1,1,1
+中国国际货运航空有限公司,中国国际货运航空有限公司,否,是,否,,1,1,1
+中国国际招标网,中国国际招标网,否,是,否,,1,1,1
+中国海洋石油集团有限公司采办业务管理与交易系统,中国海洋石油总公司采办部采购招标中心,否,是,否,,1,1,1
+中海油集团山东公司,中国海洋石油总公司采办部采购招标中心,否,是,否,,1,1,1
+中国核工业集团有限公司电子采购平台,中国核工业集团公司电子商务平台,否,否,否,,1,1,1
+中国核工业集团有限公司,中国核工业集团有限公司,否,无标讯数据,,,1,1,1
+中国华电集团电子商务平台,中国华电集团公司电子商务平台,否,否,否,,1,1,1
+中国华能集团有限公司电子商务平台,中国华能集团电子商务平台,否,是,否,,1,1,1
+中国华能集团有限公司,中国华能集团有限公司,否,无标讯数据,,,1,1,1
+中国化学电子招标投标交易平台,中国化学招标投标电子交易平台,否,是,否,,1,1,1
+中国建设银行龙集采平台,中国建设银行集采平台,否,是,否,,1,1,1
+中国建设银行集采平台,中国建设银行集采平台,否,是,否,,1,1,1
+建设银行官网,中国建设银行集采平台,否,是,否,,1,1,1
+中国节能环保集团有限公司电子采购平台,中国节能环保集团有限公司电子采购平台,否,是,否,,1,1,1
+中国科学院苏州纳米技术与纳米仿生研究所,中国科学院苏州纳米技术与纳米仿生研究所,否,是,否,,1,0,
+中国联通采购与招标网,中国联通采购与招标网,否,是,否,,1,1,1
+中国南方电网供应链统一服务平台,中国南方电网,否,是,否,,1,1,1
+中国南方电网,中国南方电网,否,是,否,,1,1,1
+中国南方电网电子采购交易平台,中国南方电网电子采购交易平台,否,是,否,,1,1,1
+中国南方航空采购招标网,中国南方航空采购招标网,否,否,否,,1,1,1
+中国能源招标网,中国能源招标网,否,已作废,,,1,1,1
+中国农业银行,中国农业银行,否,是,否,,1,1,1
+中国农业银行安徽省分行,中国农业银行安徽省分行,否,是,否,,1,1,1
+中国人寿招标采购网,中国人寿招标采购网,否,是,否,,1,1,1
+中国融通电子商务平台,中国融通电子商务平台,否,否,否,,1,1,1
+山西省政府采购信息公共平台,中国山东政府采购网,是,是,否,,1,1,1
+山东省政府采购信息公开平台,中国山东政府采购网,是,是,否,,1,1,1
+中国山东政府采购网,中国山东政府采购网,是,是,否,,1,1,1
+山东省政府采购网,中国山东政府采购网,是,是,否,,1,1,1
+山西政府采购网,中国山西政府采购网,是,是,否,,1,1,1
+山西省政府采购网,中国山西政府采购网,是,是,否,,1,1,1
+中国石化电子招标投标交易网,中国石化电子招标投标交易网,否,否,是(部分栏目需要登录),,1,1,1
+中石化齐鲁化工有限公司,中国石化物资招标投标网,否,网站打不开,,,1,1,1
+中国石化青岛炼油化工有限责任公司,中国石化物资招标投标网,否,网站打不开,,,1,1,1
+齐成(山东)石化集团有限公司,中国石化物资招标投标网,否,网站打不开,,,1,1,1
+中国石化青岛石油化工有限责任公司,中国石化物资招标投标网,否,网站打不开,,,1,1,1
+中石化集团山东公司,中国石化物资招标投标网,否,网站打不开,,,1,1,1
+中国石油招标投标网,中国石油招标投标网,否,是,否,,1,1,1
+中国石油化工股份有限公司胜利油田分公司,中国石油招标投标网,否,是,否,,1,1,1
+中石油集团山东公司,中国石油招标投标网,否,是,否,,1,1,1
+太平采购网,中国太平电子化采购平台,否,否,否,,1,1,1
+铁建商城,中国铁建商城,否,是,是(已有账号),,1,1,1
+中国铁塔,中国铁塔股份有限公司电子采购平台,否,无标讯数据,否,,1,1,1
+中国五矿集团有限公司采购电子商务平台,中国五矿集团有限公司采购电子商务平台,否,是,否,,1,1,1
+山东钢铁集团永锋临港有限公司,中国五矿集团有限公司采购电子商务平台,否,是,否,,1,1,1
+中国烟草,中国烟草,是,是,否,,1,1,1
+中国烟草公司,中国烟草,否,是,否,,1,1,1
+中国一汽电子招标采购交易平台,中国一汽电子招标采购交易平台,否,否,否,,1,1,1
+一汽解放青岛汽车有限公司,中国一汽电子招标采购交易平台,否,否,否,,1,1,1
+中国移动采购与招标网,中国移动采购与招标网,否,否,是(已有账号,部分栏目需要登录),,1,1,1
+中国邮政,中国邮政集团公司,否,否,否,,1,1,1
+中国邮政招标公告,中国邮政集团公司,否,否,否,,1,1,1
+中国远东国际招标公司,中国远东国际招标公司,否,是,否,,1,1,1
+中国长江三峡集团有限公司电子采购平台,中国长江三峡集团公司电子采购平台,否,否,否,,1,1,1
+中国招标投标公共服务平台,中国招标投标公共服务平台,是,是,否,,1,1,1
+中国招标公共服务平台,中国招标投标公共服务平台,是,是,否,,1,1,1
+中国招标与采购网,中国招标与采购网,否,是,否,,1,1,1
+中国招投标信息网,中国招投标信息网,是,否,否,,1,1,1
+地方公告_中国政府采购网,中国政府采购网,是,是,否,,1,1,1
+中央单位单一来源政府采购审核前公示_中国政府采购网,中国政府采购网,是,是,否,,1,1,1
+中央公告_中国政府采购网,中国政府采购网,是,是,否,,1,1,1
+其他采购信息_中国政府采购网,中国政府采购网,是,是,否,,1,1,1
+中央单位批量集中采集,中国政府采购网,是,是,否,,1,1,1
+中国政府采购网,中国政府采购网,是,是,否,,1,1,1
+中国政府采购网(政府网站),中国政府采购网,是,是,否,,1,1,1
+中车四方车辆有限公司,中国中车供应链管理电子采购平台,否,是,否,,1,1,1
+中化商务电子招投标平台,中国中化集团有限公司商务电子招投标平台,否,否,否,,1,1,1
+中国重型汽车集团有限公司,中国重型汽车集团有限公司,否,是,否,,1,1,1
+中航材招投标交易云平台,中航材招标投标交易信息网,否,是,是(已有账号,部分栏目需要登录),,1,1,1
+中华人民共和国财政部,中华人民共和国财政部,否,无标讯数据,否,,1,1,1
+中华人民共和国海关总署,中华人民共和国海关总署,否,是,否,,1,1,1
+中华人民共和国南宁海关,中华人民共和国南宁海关,否,是,否,,1,1,1
+中华人民共和国重庆海关,中华人民共和国重庆海关,否,是,否,,1,1,1
+中化能源股份有限公司,中化能源股份有限公司,否,否,否,,1,1,1
+中交供应商门户,中交供应商门户,否,是,是,,1,1,0
+中交集团供应链管理信息系统,中交集团供应链管理信息系统,否,是,否,,1,1,1
+中金岭南阳光采购平台,中金岭南阳光采购平台,否,是,是,,1,1,0
+中粮糖业电子采购管理平台,中粮糖业电子采购管理平台,否,是,否,,1,1,1
+中铝集团电子招投标平台,中铝集团电子招投标平台,否,是,否,,1,0,
+中煤易购采购一体化平台,中煤易购采购一体化平台,否,是,否,,1,1,1
+中煤招标与采购网,中煤招标与采购网,否,否,否,,1,1,1
+中山大学附属第七医院,中山大学附属第七医院,否,是,否,,1,1,1
+中山农村商业银行股份有限公司,中山农村商业银行股份有限公司,否,是,否,,1,1,1
+中山市公共资源交易中心,中山市公共资源交易中心,是,否,否,,1,1,1
+中山市人民医院,中山市人民医院,否,是,否,,1,1,1
+中山市人民政府,中山市人民政府,是,是,否,,1,1,1
+中山市中医院,中山市中医院,否,是,否,,1,1,1
+中山行远项目管理有限公司,中山行远项目管理有限公司,否,是,否,,1,1,1
+中山远信工程咨询招标有限公司,中山远信工程咨询招标有限公司,否,是,否,,1,1,1
+中天证券,中天证券,否,是,否,,1,1,1
+中铁鲁班商务网,中铁鲁班商务网,否,是,是(已有账号),,1,1,1
+中通服供应链管理有限公司电子招标系统,中通服供应链管理有限公司,否,是,否,,1,1,1
+中信国际招标有限公司,中信国际招标有限公司,否,是,否,,1,1,1
+中央国家机关政府采购中心电子卖场,中央国家机关政府采购中心电子卖场,是,否,否,,1,1,1
+中央国家机关政府采购中心,中央国家机关政府采购中心正版软件采购网,是,是,否,,1,0,
+中央政府采购网,中央政府采购网,是,否,否,,1,1,1
+广东中正国标中易电子交易平台,中易电子交易平台,否,否,否,,1,1,1
+中招联合招标采购网,中招联合招标采购平台,否,是,否,,1,1,1
+重庆市公共资源交易网,重庆市公共资源交易网,是,否,否,,1,1,1
+重庆市公共资源交易网_重庆市公共资源交易中心,重庆市公共资源交易网(大渡口区),是,否,否,,1,1,1
+重庆市网上中介服务超市,重庆市网上中介服务超市,是,是,否,,1,1,1
+重庆市政府采购网,重庆市政府采购网,是,是,否,,1,1,1
+重庆市政府采购云平台·服务超市,重庆市政府采购云平台·服务超市,是,是,否,,1,1,1
+重庆银行,重庆银行,否,是,否,,1,1,1
+周口市公共资源交易中心,周口市公共资源交易中心,是,是,否,,1,1,1
+珠海产权交易中心,珠海产权交易中心,否,否,否,,1,1,1
+珠海市公安局,珠海市公安局,否,是,否,,1,1,1
+珠海市公共资源交易中心,珠海市公共资源交易中心,是,否,否,,1,1,1
+珠海市交通运输局,珠海市交通运输局,否,是,否,,1,1,1
+珠海市社会保险基金管理中心,珠海市社会保险基金管理中心,否,是,否,,1,0,
+珠海市生态环境局,珠海市生态环境局,否,否,否,,1,1,1
+珠海市水务局,珠海市水务局,否,是,否,,1,1,1
+珠海市统计局,珠海市统计局,否,是,否,,1,0,
+南方医科大学附属珠海医院,珠海中西医结合医院,否,否,否,,1,1,1
+珠江啤酒采购平台,珠江啤酒采购平台,否,是,否,,1,1,1
+株洲市公共资源交易中心,株洲市公共资源交易中心,是,否,否,,1,1,1
+驻马店市公共资源交易中心,驻马店市公共资源交易中心,是,否,否,,1,1,1
+资阳市公共资源交易中心,资阳市公共资源交易中心,是,否,否,,1,1,1
+淄博市公共资源交易网,淄博市公共资源交易网,是,是,否,,1,1,1
+遵义市公共资源交易中心,遵义市公共资源交易中心,是,否,否,,1,1,1
+贵州兴亚利达电子招投标平台,贵州兴业利达电子招投标交易平台,否,是,,是,1,1,1
+仪征市政府采购网,扬州市仪征政府采购网,是,是,,是,1,1,1
+徐州市公共资源交易中心,,是,,,无效网站,0,1,1
+盐城市公共资源交易中心,徐州市公共资源建设交易平台,是,是,,是,1,1,1
+必联网,必联电子招标投标平台,否,是,是(部分栏目需要登录),是,1,1,0
+保标招标网(第三方聚合网站),保标招标,否,否,是(注册会员),竞品网站,1,1,2
+佰中标讯网,,否,,,无效网站,0,1,1
+黑龙江省投标网,乙方宝,否,否,是(注册会员),竞品网站,1,1,2
+哈尔滨招标网,乙方宝,否,否,是,竞品网站,1,1,2
+全国公共资源交易平台(四川省.德阳市),德阳市公共资源交易信息网,是,是,,是,1,1,1
+寰亚新点电子交易平台,安徽寰亚国际招标有限公司,否,是,,是,1,1,1
+德州市政府采购网,,是,,,无效网站,0,1,1
+聊城市公共资源交易中心,,是,,,网站打不开,0,1,1
+菏泽市政府采购(招标投标),,是,,,网站打不开,0,1,1
+枣庄市政府采购网,,是,,,网站打不开,0,1,1
+剑鱼标讯,,否,,,剑鱼平台,0,1,1
+常德市公共资源交易中心,常德市公共资源交易中心,是,是,,是,1,1,1
+湘西公共交易资源网,湘西公共资源交易网,是,否-已补录,,是,1,1,1
+湘西州公共资源交易服务平台,湖南省公共资源交易服务平台新网址,是,,,是,1,1,1
+Title,,否,,,无效网站,0,1,1
+北交所电子采购平台,北京产权交易所,否,是,,是,1,1,1
+济源市公共资源交易中心,济源市公共资源交易网,是,是,,是,1,1,1
+广州公共资源交易中心,广东省公共资源交易平台,是,是,,是,1,1,1
+深圳公共资源交易中心光明分公司,,是,,,网站打不开,0,1,1
+深圳公共资源交易中心龙岗分公司,,是,,,网站打不开,0,1,1
+阳江市公共资源交易中心,阳江市公共资源交易信息化平台,是,否-已补录,,是,1,1,1
+中国深圳政府采购,深圳政府采购网,是,否,否,是,1,1,1
+广东黄埔海关,中华人民共和国黄埔海关,否,是,,是,1,1,1
+广州市应急管理局,广州市应急管理局,否,,,是,1,1,1
+广州市南沙区人民政府,广州市南沙区人民政府网,是,否-已补录,,是,1,1,1
+广州市白云区人民政府,广州市白云区人民政府网,是,否-已补录,,是,1,1,1
+广州市荔湾区经济联社“三资 ”交易服务中心,,否,,,网站打不开,0,1,1
+广州市农村(社区)集体产权流转管理服务平台,广州市农村产权流转交易管理服务平台,否,是,,已补录,1,1,1
+黄埔区农村集体经济组织资产财务管理服务中心,,否,,,网站打不开,0,1,1
+东莞市工信局,东莞市工业和信息化局,否,是,,是,1,1,1
+东莞市农村(社区)集体资产管理网,东莞市农村集体资产管理网,否,是,否,是,1,1,1
+珠海市卫生健康局,珠海市卫生健康局,否,否,否,否-已补录,1,1,1
+珠海市斗门区人民政府,珠海市斗门区人民政府网,是,否-已补录,,是,1,1,1
+深圳市盐田政府在线,深圳市盐田区人民政府,是,否-已补录,,是,1,1,1
+湛江市财政局,,否,,,网站打不开,0,1,1
+汕头海关,中华人民共和国汕头海关,否,是,否,是,1,1,1
+惠州交通运输局,惠州市交通运输局,否,是,否,是,1,1,1
+中山市退役军人事务局,中山市人民政府,否,是,否,是,1,1,1
+惠州市市场监管局,惠州市市场监督管理局,否,是,否,是,1,1,1
+佛山市南海区人民政府,佛山市南海区人民政府网,是,否,否,是,1,1,1
+佛山市三水区人民政府,佛山市三水区人民政府网,是,否,否,是,1,1,1
+珠海市高新技术产额开发区管理委员会,珠海高新技术产业开发区管理委员会,否,否,否,是,1,1,1
+华南理工大学招投标中心,华南理工大学招标中心,否,,,是,1,1,1
+广州南华工商职业学院,广东南华工商职业学院,否,是,否,是,1,1,1
+东莞理工学院,东莞理工学院招标与采购管理中心,否,是,否,是,1,1,1
+深圳大学,深圳大学招投标管理中心,否,否,否,是,1,1,1
+佛山科学技术学院,佛山大学招标采购中心,否,是,否,是,1,1,1
+顺为电子招投标系统,广州顺为招标采购有限公司,否,否-已补录,,是,1,1,1
+深圳市建设工程交易服务中心,,否,,,网站打不开,0,1,0
+58同城招标服务,无有效信息,否,,,否,1,1,1
+中国远东国际招标有限公司,中国远东国际招标公司,否,是,否,是,1,1,1
+中国汽车供应商网,中国汽车供应商网,否,,否,否-已补录,1,1,1
+中国节能电子采购平台,中国节能环保集团有限公司电子采购平台,否,是,否,是,1,1,1
+国家电网有限公司电子商务平台,国家电网公司电子商务平台电工交易专区,否,是,否,是,1,1,1
+广东省南方文化产权交易所股份有限公司,广东省南方文化产权交易所,否,是,,是,1,1,1
+中化集团商务电子招投标平台,中国中化集团有限公司商务电子招投标平台,否,是,否,是,1,1,1
+中国人民保险集团人保e采,人保e采外网门户,否,是,否,是,1,1,1
+企查查-标找找一站式标讯服务平台,标找找,否,,是(注册会员),竞品网站,1,1,2
+国家电力投资集团有限公司,,否,,,无有效信息,0,1,1
+平安采购信息管理平台,,否,,,网站打不开,0,1,1
+欧贝-工业品供应链生态平台,欧贝易购,否,是,,是,1,1,1
+浙江省政府采购网,浙江政府采购网,是,是,否,是,1,1,1
+河北省公共资源交易服务平台,河北省公共资源交易中心,是,否-已补录,,是,1,1,1
+黑龙江省公共资源交易网,黑龙江公共资源交易中心,是,否-已补录,,是,1,1,1
+西藏自治区公共资源交易网,西藏公共资源交易平台,是,否-已补录,,是,1,1,1
+新疆维吾尔自治区公共资源交易网,新疆公共资源交易网,是,否-已补录,,是,1,1,1
+青州市公共资源交易中心,,否,,,网站打不开,0,1,1
+日照招标网,,否,,,非有效网站,0,1,1
+电力招标网,,否,,是(注册会员),否,0,1,0
+国际机电设备招标采购平台,,否,,是(注册会员),否,0,1,0
+采招网,,否,,是(注册会员),否,0,1,0
+山东能源集团,山东能源招标交易平台,否,是,,是,1,1,1
+兖矿能源集团股份有限公司,,否,,,无有效信息,0,1,1
+临沂矿业集团有限责任公司,,否,,,查不到该网站,0,1,1
+龙口矿业集团有限公司,,否,,,查不到该网站,0,1,1
+枣庄矿业(集团)有限责任公司,山东能源枣庄矿业集团有限责任公司,否,,,是,1,1,1
+山东东明石化集团有限公司,,否,,,无有效信息,0,1,1
+万达控股集团有限公司,,否,,,无有效信息,0,1,1
+永锋集团有限公司,,否,,是,否,0,1,0
+歌尔集团有限公司,,否,,,无有效信息,0,1,1
+华泰集团有限公司,,否,,,网站打不开,0,1,1
+山东京博控股集团有限公司,,否,,,无有效信息,0,1,1
+山东海科控股有限公司,,否,,,网站打不开,0,1,1
+浪潮集团有限公司,,否,,,无有效信息,0,1,1
+山东金诚石化集团有限公司,金诚石化,否,否-已补录,是,否-已补录,1,1,0
+中化弘润石油化工有限公司,,否,,,网站打不开,0,1,1
+山东如意科技集团有限公司,,否,,,无有效信息,0,1,1
+山东太阳纸业股份有限公司,无有效信息,否,,,无有效信息,1,1,1
+富海集团有限公司,,否,,,无有效信息,0,1,1
+山东富海集团有限公司,,否,,,无有效信息,0,1,1
+山东恒源石油化工股份有限公司,,否,,,网站打不开,0,1,1
+威高集团有限公司,,否,,,无有效信息,0,1,1
+东营齐润化工有限公司,,否,,,无有效信息,0,1,1
+山东招金集团,,否,,,网站打不开,0,1,1
+西王集团有限公司,,否,,,无有效信息,0,1,1
+山东渤海实业集团有限公司,,否,,,无有效信息,0,1,1
+鸿富锦精密电子(烟台)有限公司,,否,,,查不到该网站,0,1,1
+鸿富锦精密电子(烟台)有限公司,,否,,,查不到该网站,0,1,1
+山东汇丰石化集团有限公司,,否,,,无有效信息,0,1,1
+山东寿光鲁清石化有限公司,,否,,,查不到该网站,0,1,1
+山东清源集团有限公司,,否,,,查不到该网站,0,1,1
+山东华鲁恒升集团有限公司,山东华鲁恒升集团有限公司,否,,,否-已补录,1,1,1
+华鲁控股集团有限公司,华鲁控股集团有限公司,否,,,否-已补录,1,0,
+山东垦利石化集团有限公司,山东垦利石化集团有限公司,否,,,否-已补录,1,1,1
+道恩集团有限公司,,否,,,无有效信息,0,1,1
+淄博齐翔腾达化工股份有限公司,,否,,,无有效信息,0,1,1
+山东中海化工集团有限公司,,否,,,无有效信息,0,1,1
+山东东方华龙工贸集团有限公司,,否,,,查不到该网站,0,1,1
+万通海欣控股集团股份有限公司,万通海欣控股集团股份有限公司,否,,,否-已补录,1,1,1
+山东新希望六和集团有限公司,,否,,,无数据,0,1,1
+香驰控股有限公司,,否,,,无有效信息,0,1,1
+淄博鑫泰石化有限公司,淄博鑫泰石化有限公司,否,,,否-已补录,1,1,1
+山东昌邑石化有限公司,,否,,,查不到该网站,0,1,1
+山东神驰控股有限公司,,否,,,无有效信息,0,1,1
+山东永鑫能源集团有限公司,,否,,,无有效信息,0,1,1
+山东东岳氟硅材料有限公司,东岳集团,否,,,否-已补录,1,0,
+上汽通用东岳汽车有限公司,,否,,,查不到该网站,0,1,1
+山东山水水泥集团有限公司,,否,,,查不到该网站,0,1,1
+淄博山水水泥有限公司,,否,,,查不到该网站,0,1,1
+滨化集团股份有限公司,,否,,,无有效信息,0,1,1
+诸城外贸有限责任公司,,否,,,查不到该网站,0,1,1
+山东寿光巨能集团有限公司,,否,,,无有效信息,0,1,1
+上汽通用五菱汽车股份有限公司青岛分公司,,否,,,查不到该网站,0,1,1
+山东联盟化工股份有限公司,山东联盟化工集团有限公司,否,否-已补录,,否-已补录,1,1,1
+青岛特殊钢铁有限公司,,否,,,无有效信息,0,1,1
+山东龙大美食股份有限公司,,否,,,无有效信息,0,1,1
+正和集团股份有限公司,,否,,,无有效信息,0,1,1
+山东鑫海科技股份有限公司,,否,,,无有效信息,0,1,1
+临工重机股份有限公司,,否,,,近两年无数据,0,1,1
+山东临工工程机械有限公司,,否,,,无有效信息,0,1,1
+赛轮集团股份有限公司,,否,,,无有效信息,0,1,1
+金猴集团有限公司,,否,,,无有效信息,0,1,1
+迪尚集团有限公司,迪尚集团有限公司,否,否-已补录,,否-已补录,1,1,1
+青岛海湾集团有限公司,,否,,,无有效信息,0,1,1
+山东胜星化工有限公司,,否,,,无有效信息,0,1,1
+山东荣信集团有限公司,,否,,是,否,0,1,0
+英科医疗科技股份有限公司,,否,,,无有效信息,0,1,1
+青岛康大食品有限公司,康大集团采购平台,否,是,,是,1,1,1
+斗山工程机械(中国)有限公司,,否,,,查不到该网站,0,1,1
+格力电器(临沂)有限公司,,否,,,查不到该网站,0,1,1
+山东岱银纺织集团股份有限公司,,否,,,无有效信息,0,1,1
+山东鲁碧建材有限公司,,否,,,查不到该网站,0,1,1
+山东新时代药业有限公司,,否,,,查不到该网站,0,1,1
+兖矿鲁南化工有限公司,山东能源招标交易平台,否,,,是,1,1,1
+愉悦家纺有限公司,,否,,,无有效信息,0,1,1
+中国船舶集团青岛北海造船有限公司,,否,,,无有效信息,0,1,1
+中国联合水泥集团有限公司,,否,,,查不到该网站,0,1,1
+临沂中联水泥有限公司,,否,,,近两年无数据,0,1,1
+泰安中联水泥有限公司,,否,,,网站打不开,0,1,1
+枣庄中联水泥有限公司,,否,,,查不到该网站,0,1,1
+中国烟草总公司山东省公司,,否,,,查不到该网站,0,1,1
+山东中烟工业有限责任公司青岛卷烟厂,,否,,,无有效信息,0,1,1
+山东中烟工业有限责任公司青州卷烟厂,,否,,,无有效信息,0,1,1
+山东中烟工业有限责任公司滕州卷烟厂,,否,,,无有效信息,0,1,1

BIN
tools/联通项目/字段缺失率/.~字段缺失率基础数据.xlsx


+ 165 - 0
tools/联通项目/字段缺失率/基础数据入库.py

@@ -0,0 +1,165 @@
+import pandas as pd
+import pymysql
+from pymysql.cursors import DictCursor
+from typing import List, Dict
+import logging
+import numpy as np
+# 配置日志
+logging.basicConfig(level=logging.INFO)
+logger = logging.getLogger(__name__)
+
+
+class TiDBFieldNullStatsLoader:
+    def __init__(self, tidb_config: Dict):
+        """
+        初始化TiDB连接配置
+        :param tidb_config: {
+            'host': '127.0.0.1',
+            'port': 4000,
+            'user': 'root',
+            'password': '',
+            'database': 'test'
+        }
+        """
+        self.tidb_config = tidb_config
+        self.table_name = 'field_null_stats_liantong'
+
+
+    def _get_connection(self):
+        """获取TiDB数据库连接"""
+        return pymysql.connect(
+            host=self.tidb_config['host'],
+            port=self.tidb_config['port'],
+            user=self.tidb_config['user'],
+            password=self.tidb_config['password'],
+            database=self.tidb_config['database'],
+            charset='utf8mb4',
+            cursorclass=DictCursor
+        )
+
+    def _deep_clean_data(self, df: pd.DataFrame) -> List[tuple]:
+        """深度数据清洗,确保100%无NaN"""
+        clean_data = []
+        for _, row in df.iterrows():
+            # 处理每个字段,确保无NaN/None/空值问题
+            field_name = str(row.get('字段', ''))[:128] or 'unknown_field'
+            field_type = str(row.get('类型', ''))[:64] or 'varchar'
+
+            # 处理是否允许为空(防御性转换)
+            try:
+                nullable = 1 if str(row.get('是否允许为空', '')).lower() in ('是', 'yes', 'true', '1', 'y') else 0
+            except:
+                nullable = 0
+
+            # 处理为空比例(终极防御)
+            null_ratio = None
+            ratio_val = row.get('为空比例', None)
+            if ratio_val is not None and not pd.isna(ratio_val):
+                try:
+                    if isinstance(ratio_val, str):
+                        ratio_val = ratio_val.strip().replace('%', '')
+                    null_ratio = min(1.0,
+                                     max(0.0, float(ratio_val) / 100 if '%' in str(ratio_val) else float(ratio_val)))
+                except (ValueError, TypeError):
+                    null_ratio = None
+
+            # 处理来源
+            data_source = str(row.get('来源', 'excel'))[:64] if pd.notna(row.get('来源')) else 'excel'
+
+            clean_data.append((
+                field_name,
+                field_type,
+                nullable,
+                null_ratio,
+                data_source
+            ))
+        return clean_data
+
+    def _prepare_batch_data(self, df: pd.DataFrame) -> List[tuple]:
+        """生成安全的插入数据"""
+        batch_data = []
+        for _, row in df.iterrows():
+            # 显式转换每个字段为SQL安全值
+            safe_row = (
+                str(row['字段'])[:128],
+                str(row['类型'])[:64],
+                int(row['是否允许为空']),
+                float(row['为空比例']) if row['为空比例'] is not None else None,
+                str(row.get('来源', 'excel'))[:64] if pd.notna(row.get('来源')) else None
+            )
+            batch_data.append(safe_row)
+        return batch_data
+    def _convert_null_ratio(self, ratio_str: str) -> float:
+        """
+        更健壮的百分比转换处理
+        :param ratio_str: 输入值(可能是"60%", "0.6", NaN等)
+        :return: 标准化小数或None
+        """
+        if pd.isna(ratio_str) or ratio_str in ['', 'NaN', 'nan', 'None']:
+            return None
+
+        try:
+            if isinstance(ratio_str, (int, float)):
+                return float(ratio_str) / 100 if ratio_str > 1 else float(ratio_str)
+
+            ratio_str = str(ratio_str).strip()
+            if '%' in ratio_str:
+                return float(ratio_str.replace('%', '')) / 100
+            return float(ratio_str)
+        except (ValueError, TypeError):
+            return None
+
+    def load_from_excel(self, excel_path: str, sheet_name: str = '基础数据'):
+        """
+        从Excel文件加载数据到TiDB
+        :param excel_path: Excel文件路径
+        :param sheet_name: 指定sheet名称(可选)
+        """
+        # 1. 读取Excel数据
+        try:
+            # 1. 读取数据(禁用pandas自动转换空字符串)
+            df = pd.read_excel(excel_path, sheet_name=sheet_name, keep_default_na=False, na_values=[''])
+            logger.info(f"成功读取Excel文件: {excel_path}, 共{len(df)}条记录")
+
+            # 2. 深度清洗
+            batch_data = self._deep_clean_data(df)
+            # 3. 最终检查
+            for data in batch_data:
+                if any(isinstance(x, float) and np.isnan(x) for x in data):
+                    raise ValueError(f"发现未处理的NaN值: {data}")
+            # 4. 数据库操作
+            with self._get_connection() as conn:
+                with conn.cursor() as cursor:
+                    sql = f"""
+                           INSERT INTO {self.table_name} (
+                                field_name, field_type, 
+                               is_nullable, null_ratio, data_source
+                           ) VALUES ( %s, %s, %s, %s, %s)
+                           """
+                    cursor.executemany(sql, batch_data)
+                conn.commit()
+
+        except Exception as e:
+            logger.error(f"处理失败,最后5条数据示例: {batch_data[-5:]}")
+            raise RuntimeError(f"数据入库失败: {str(e)}") from e
+
+# 使用示例
+if __name__ == "__main__":
+    # TiDB连接配置
+    tidb_config = {
+        "host": "172.20.45.129",
+        "port": 4000,
+        "user": "root",
+        "password": "=PDT49#80Z!RVv52_z",
+        "database": "quality"
+    }
+
+    # 创建加载器实例
+    loader = TiDBFieldNullStatsLoader(tidb_config)
+
+    # 从Excel加载数据
+    try:
+        loader.load_from_excel('字段缺失率基础数据.xlsx')
+        logger.info("数据加载完成")
+    except Exception as e:
+        logger.error(f"数据处理失败: {str(e)}")

BIN
tools/联通项目/字段缺失率/字段缺失率基础数据.xlsx


BIN
tools/联通项目/数据时效统计表.xlsx


BIN
tools/联通项目/新闻类覆盖率/news_site_liantong.xlsx


BIN
tools/联通项目/新闻类覆盖率/news_site_liantong_area.xlsx


+ 6 - 0
tools/联通项目/新闻类覆盖率/test.py

@@ -0,0 +1,6 @@
+from selenium import webdriver
+
+driver = webdriver.Chrome()
+driver.get("https://www.nmpa.gov.cn")
+print("页面标题:", driver.title)  # 能获取标题说明可访问
+driver.quit()

+ 109 - 0
tools/联通项目/新闻类覆盖率/判断站点是否有效.py

@@ -0,0 +1,109 @@
+import pymysql
+import requests
+from concurrent.futures import ThreadPoolExecutor, as_completed
+
+# 数据库配置
+DB_CONFIG = {
+        "host": "172.20.45.129",
+        "port": 4000,
+        "user": "root",
+        "password": "=PDT49#80Z!RVv52_z",
+        "database": "quality"
+}
+
+# 请求配置
+REQUEST_TIMEOUT = 40  # 超时时间(秒)
+
+HEADERS = {
+    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
+    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
+    'Accept-Encoding': 'gzip, deflate, br',
+    'Connection': 'keep-alive',
+    'Upgrade-Insecure-Requests': '1',  # 模拟浏览器自动升级HTTPS
+}
+
+def is_url_valid(url, retries=5):
+    """检查URL是否可访问"""
+    if not url or not url.startswith(('http://', 'https://')):
+        return False
+    # 主动将HTTP改为HTTPS(避免重定向)
+    if url.startswith('http://'):
+        url = url.replace('http://', 'https://', 1)
+    for _ in range(retries + 1):
+        try:
+            # # 先尝试HEAD请求
+            # response = requests.head(url, headers=HEADERS, timeout=REQUEST_TIMEOUT, allow_redirects=True,verify=False)
+            # if response.status_code == 200:
+            #     return True
+            # 如果HEAD返回非200,尝试GET请求
+            response = requests.get(url, headers=HEADERS, timeout=REQUEST_TIMEOUT, allow_redirects=True,verify=False)
+            return response.status_code == 200
+        except requests.exceptions.Timeout:
+            continue
+        except (requests.RequestException, ValueError):
+            break
+    return False
+
+
+def update_url_validity(db_config, url_id, is_valid):
+    """更新数据库中URL的有效性状态"""
+    try:
+        conn = pymysql.connect(**db_config)
+        with conn.cursor() as cursor:
+            sql = "UPDATE news_site_liantong SET url_valid = %s, updated_at = CURRENT_TIMESTAMP WHERE id = %s"
+            cursor.execute(sql, (1 if is_valid else 0, url_id))
+        conn.commit()
+    except Exception as e:
+        print(f"更新数据库时出错(ID:{url_id}): {e}")
+    finally:
+        if 'conn' in locals() and conn:
+            conn.close()
+
+
+def get_all_urls(db_config):
+    """获取所有需要检查的URL"""
+    try:
+        conn = pymysql.connect(**db_config)
+        with conn.cursor() as cursor:
+            cursor.execute("SELECT id, url FROM news_site_liantong where url_valid=0")
+            return cursor.fetchall()
+    except Exception as e:
+        print(f"获取URL列表时出错: {e}")
+        return []
+    finally:
+        if 'conn' in locals() and conn:
+            conn.close()
+
+
+def process_single_url(db_config, url_item):
+    """处理单个URL"""
+    url_id, url = url_item
+    is_valid = is_url_valid(url)
+    update_url_validity(db_config, url_id, is_valid)
+    print(f"URL ID: {url_id}, URL: {url}, 有效性: {'有效' if is_valid else '无效'}")
+    return url_id, is_valid
+
+
+def process_urls():
+    """处理所有URL"""
+    urls = get_all_urls(DB_CONFIG)
+    if not urls:
+        print("没有找到需要检查的URL")
+        return
+
+    print(f"共找到 {len(urls)} 个URL需要检查")
+
+    # 使用多线程加速检查
+    with ThreadPoolExecutor(max_workers=10) as executor:
+        futures = [executor.submit(process_single_url, DB_CONFIG, url) for url in urls]
+
+        for future in as_completed(futures):
+            try:
+                future.result()
+            except Exception as e:
+                print(f"处理URL时出错: {e}")
+
+
+if __name__ == '__main__':
+    process_urls()
+    print("URL有效性检查完成")

+ 57 - 0
tools/联通项目/新闻类覆盖率/寻找原始网站.py

@@ -0,0 +1,57 @@
+import requests
+from docx import Document
+import PyPDF2
+from openpyxl import Workbook
+from io import BytesIO
+
+
+def call_llm_api(content):
+    """调用大语言模型API"""
+    # 免费token:sk-109b72d2d2e0409cb0571bb44d8f21a6
+    url = "https://ark.cn-beijing.volces.com/api/v3/chat/completions"  #豆包
+    # url = "https://open.bigmodel.cn/api/paas/v4/chat/completions"    #免费
+    headers = {
+        "Authorization": "Bearer 3dd861bf-b8a7-41d4-bb0b-5076362c572d",  #豆包
+        # "Authorization": "Bearer 3d84d30b7ab4c94dbf71853cb7e44719.hLLS4CA2MqVQs6kR",  #免费
+        "Content-Type": "application/json"
+    }
+
+    # 构造系统提示词
+    system_prompt = """请根据我提供的名称,输出该名称对应的站点名称及网址"""
+    messages = [
+        {
+            # "role": "system",
+            "role": "user",
+            "content": system_prompt
+        },
+        {
+            "role": "user",
+            "content": f"名称:\n{content}"
+        }
+    ]
+    #豆包
+    data = {
+        "model": "ep-20250207170552-g8dsx",
+        "temperature": 0.1,
+        "top_p": 0.7,
+        "messages": messages
+    }
+    #免费
+    # data = {
+    #     "model": "glm-4-flash",
+    #     "messages": messages,
+    #     "temperature": 0.1,
+    #     "max_tokens": 4096,
+    # }
+
+    try:
+        response = requests.post(url, json=data, headers=headers, timeout=480)
+        response.raise_for_status()
+        print(response.json()['choices'][0]['message']['content'])
+        return response.json()['choices'][0]['message']['content']
+    except Exception as e:
+        raise RuntimeError(f"API调用失败: {str(e)}")
+
+
+if __name__ == '__main__':
+    site,url= call_llm_api("外交部")

+ 369 - 0
tools/联通项目/新闻类覆盖率/寻找原始网站_v1.py

@@ -0,0 +1,369 @@
+import json
+import re
+import time
+import requests
+import pymysql
+from urllib.parse import urlparse
+from requests.exceptions import RequestException
+from pymysql import MySQLError
+from typing import List, Dict, Tuple, Optional
+import openpyxl
+class LLMAPIError(Exception):
+    """自定义API异常类"""
+    pass
+
+class DatabaseError(Exception):
+    """自定义数据库异常类"""
+    pass
+
+class MySQLStorage:
+    def __init__(self, host: str, user: str, password: str, database: str, port: int = 3306):
+        """初始化MySQL连接"""
+        self.host = host
+        self.user = user
+        self.password = password
+        self.database = database
+        self.port = port
+        self.connection = None
+
+    def connect(self):
+        """建立数据库连接"""
+        try:
+            self.connection = pymysql.connect(
+                host=self.host,
+                user=self.user,
+                password=self.password,
+                database=self.database,
+                port=self.port,
+                charset='utf8mb4',
+                cursorclass=pymysql.cursors.DictCursor
+            )
+        except MySQLError as e:
+            raise DatabaseError(f"数据库连接失败: {str(e)}")
+
+    def disconnect(self):
+        """关闭数据库连接"""
+        if self.connection:
+            self.connection.close()
+            self.connection = None
+
+    def import_from_excel(self, llm_client,db_storage,file_path: str,target_sheets: List[str] = None):
+        """从Excel文件导入数据到数据库"""
+        try:
+            # 打开Excel文件
+            wb = openpyxl.load_workbook(file_path, read_only=True)
+
+            # 获取所有sheet名称(即类别)
+            categories = wb.sheetnames
+
+            # 获取要处理的sheet列表
+            sheets_to_process = target_sheets if target_sheets else wb.sheetnames
+
+            for category in sheets_to_process:
+                print(f"\n正在处理类别: {category}")
+                sheet = wb[category]
+
+                # 读取sheet中的数据
+                for row in sheet.iter_rows(min_row=2, values_only=True):  # 假设第一行是标题
+                    query_name = row[0]  # 假设第一列是query_name
+
+                    if not query_name:  # 跳过空行
+                        continue
+
+                    # 调用API获取站点信息(这里需要你原有的API调用逻辑)
+                    try:
+                        # 调用API获取信息
+                        response = llm_client.call_llm_api(query_name)
+                        site_name, site_url = llm_client.extract_site_info(response)
+
+                        print(f"提取结果 - 站点名称: {site_name}, 网址: {site_url}")
+
+                        # 存储到数据库
+                        db_storage.save_site_info(category,query_name, site_name, site_url)
+                        print("数据已保存到数据库")
+
+                    except LLMAPIError as e:
+                        print(f"API调用错误: {str(e)}")
+                        # 即使API失败也记录查询名称
+                        db_storage.save_site_info(category,query_name, None, None)
+                    except Exception as e:
+                        print(f"处理过程中发生意外错误: {str(e)}")
+
+        except Exception as e:
+            raise DatabaseError(f"导入Excel数据失败: {str(e)}")
+        finally:
+            if 'wb' in locals():
+                wb.close()
+
+    def process_special_sheet(self,file_path: str, sheet_name: str = '省各个厅局') -> Dict[str, List[str]]:
+        """处理特殊sheet并生成各省厅局名称
+
+        Args:
+            file_path: Excel文件路径
+            sheet_name: 要处理的sheet名称
+
+        Returns:
+            字典格式:{省份全称: [厅局名称列表]}
+        """
+        # 31个省、自治区、直辖市全称列表(不使用简称)
+        provinces = [
+            "河北省", "山西省", "辽宁省", "吉林省", "黑龙江省",
+            "江苏省", "浙江省", "安徽省", "福建省", "江西省",
+            "山东省", "河南省", "湖北省", "湖南省", "广东省",
+            "海南省", "四川省", "贵州省", "云南省", "陕西省",
+            "甘肃省", "青海省", "内蒙古自治区", "广西壮族自治区", "西藏自治区",
+            "宁夏回族自治区", "新疆维吾尔自治区", "北京市", "天津市", "上海市",
+            "重庆市"
+        ]
+
+        # 读取Excel文件
+        wb = openpyxl.load_workbook(file_path, read_only=True)
+        sheet = wb[sheet_name]
+
+        # 获取河南省厅局原始名称(从第二行开始)
+        original_names = []
+        for row in sheet.iter_rows(min_row=2, values_only=True):  # 跳过标题行
+            if row and row[0]:
+                original_names.append(str(row[0]))
+
+        wb.close()
+
+        # 生成各省厅局名称
+        result = {}
+        for province in provinces:
+            province_departments = []
+            for name in original_names:
+                # 替换"河南省"为当前省份全称
+                new_name = name.replace("河南省", province)
+                province_departments.append(new_name)
+            result[province] = province_departments
+
+        return result
+
+    def import_special_site_from_excel(self, llm_client,db_storage,file_path: str):
+        """从Excel文件导入数据到数据库"""
+        try:
+            result = self.process_special_sheet(file_path)
+            for sheet_name in result:
+                    for query_name in result[sheet_name]:
+                        try:
+                            # 调用API获取信息
+                            response = llm_client.call_llm_api(query_name)
+                            site_name, site_url = llm_client.extract_site_info(response)
+
+                            print(f"提取结果 - 站点名称: {site_name}, 网址: {site_url}")
+
+                            # 存储到数据库
+                            db_storage.save_site_info(sheet_name,query_name, site_name, site_url)
+                            print("数据已保存到数据库")
+
+                        except LLMAPIError as e:
+                            print(f"API调用错误: {str(e)}")
+                            # 即使API失败也记录查询名称
+                            db_storage.save_site_info(sheet_name,query_name, None, None)
+                        except Exception as e:
+                            print(f"处理过程中发生意外错误: {str(e)}")
+
+        except Exception as e:
+            raise DatabaseError(f"导入Excel数据失败: {str(e)}")
+
+    def save_site_info(self,category, query_name: json, site_name: Optional[str], site_url: Optional[str]) -> bool:
+        """保存站点信息到数据库"""
+        if not self.connection:
+            raise DatabaseError("数据库未连接")
+        # 从字典中提取出实际名称(如从 {'名称': '教育部'} 提取 "教育部")
+        try:
+            actual_name = query_name['名称']  # 获取字典中的值
+        except (KeyError, TypeError):
+            # 如果格式不符合预期,尝试直接使用传入的值
+            actual_name = str(query_name)
+        # 处理None值
+        site_name = site_name if site_name is not None else "未知"
+        site_url = site_url if site_url is not None else "无"
+
+        sql = """
+        INSERT INTO news_site_liantong (category, name, site, url)
+        VALUES (%s,%s, %s, %s)
+        """
+        try:
+            with self.connection.cursor() as cursor:
+                # 确保参数是字符串类型
+                params = (
+                    str(category) if category is not None else "未知",
+                    str(actual_name) if actual_name is not None else "未知",
+                    str(site_name) if site_name is not None else "未知",
+                    str(site_url) if site_url is not None else "无"
+                )
+                cursor.execute(sql, params)
+            self.connection.commit()
+            return True
+        except MySQLError as e:
+            raise DatabaseError(f"保存数据失败: {str(e)}")
+
+class LLMClient:
+    def __init__(self):
+        # 注意:在实际应用中应该使用环境变量或配置文件存储这些信息
+        self.api_url = "https://ark.cn-beijing.volces.com/api/v3/chat/completions"
+        self.api_key = "3dd861bf-b8a7-41d4-bb0b-5076362c572d"
+        self.model = "ep-20250207170552-g8dsx"
+        self.max_retries = 3
+        self.timeout = 480
+
+    def _make_request(self, data: dict) -> dict:
+        """执行API请求"""
+        headers = {
+            "Authorization": f"Bearer {self.api_key}",
+            "Content-Type": "application/json"
+        }
+
+        for attempt in range(self.max_retries):
+            try:
+                response = requests.post(
+                    self.api_url,
+                    json=data,
+                    headers=headers,
+                    timeout=self.timeout
+                )
+                response.raise_for_status()
+                return response.json()
+            except RequestException as e:
+                if attempt == self.max_retries - 1:
+                    raise LLMAPIError(f"API请求失败,重试{self.max_retries}次后仍不成功: {str(e)}")
+                time.sleep(2 ** attempt)  # 指数退避
+
+    def _validate_url(self, url: str) -> bool:
+        """验证URL格式是否有效"""
+        try:
+            result = urlparse(url)
+            return all([result.scheme in ['http', 'https'], result.netloc])
+        except:
+            return False
+
+    def call_llm_api(self, content: str) -> str:
+        """调用大语言模型API"""
+        system_prompt = """请根据我提供的名称,严格按照以下JSON格式输出响应:
+{
+    "站点名称": "准确的官方名称",
+    "网址": "完整的官网URL(必须以http://或https://开头)"
+}
+
+请确保:
+1. 只返回标准的JSON格式,不要包含任何额外文字
+2. 网址必须是可访问的官方网站URL
+3. 如果无法确定,请将对应字段设为null"""
+
+        messages = [
+            {"role": "system", "content": system_prompt},
+            {"role": "user", "content": f"名称:{content}"}
+        ]
+
+        data = {
+            "model": self.model,
+            "temperature": 0.1,
+            "top_p": 0.7,
+            "messages": messages,
+            "response_format": {"type": "json_object"}  # 强制JSON格式输出
+        }
+
+        try:
+            response = self._make_request(data)
+            return response['choices'][0]['message']['content']
+        except (KeyError, TypeError) as e:
+            raise LLMAPIError(f"解析API响应失败: {str(e)}")
+
+    def extract_site_info(self, content: str) -> Tuple[Optional[str], Optional[str]]:
+        """从API响应中提取站点名称和URL"""
+        try:
+            # 预处理响应内容
+            content = content.strip()
+
+            # 处理可能的Markdown代码块
+            if content.startswith("```") and content.endswith("```"):
+                content = content[3:-3].strip()
+                if content.startswith("json"):
+                    content = content[4:].strip()
+
+            # 统一引号格式
+            content = re.sub(r'[“”]', '"', content)
+            content = re.sub(r'[‘’]', "'", content)
+
+            # 尝试解析为JSON
+            try:
+                data = json.loads(content)
+                site_name = data.get("站点名称")
+                site_url = data.get("网址")
+
+                # 验证URL
+                if site_url and not self._validate_url(site_url):
+                    print(f"警告:无效的URL格式 - {site_url}")
+                    site_url = None
+
+                return site_name, site_url
+
+            except json.JSONDecodeError:
+                # 如果不是标准JSON,尝试用正则表达式提取
+                pattern = r'{\s*"站点名称"\s*:\s*"(?P<name>[^"]+)"\s*,\s*"网址"\s*:\s*"(?P<url>[^"]+)"\s*}'
+                match = re.search(pattern, content)
+                if match:
+                    site_name = match.group("name")
+                    site_url = match.group("url")
+                    if not self._validate_url(site_url):
+                        print(f"警告:无效的URL格式 - {site_url}")
+                        site_url = None
+                    return site_name, site_url
+
+                # 最后尝试宽松匹配
+                name_match = re.search(r'"站点名称"\s*:\s*"([^"]+)"', content)
+                url_match = re.search(r'"网址"\s*:\s*"([^"]+)"', content)
+
+                site_name = name_match.group(1) if name_match else None
+                site_url = url_match.group(1) if url_match else None
+
+                if site_url and not self._validate_url(site_url):
+                    print(f"警告:无效的URL格式 - {site_url}")
+                    site_url = None
+
+                return site_name, site_url
+
+        except Exception as e:
+            print(f"解析站点信息时出错: {str(e)}")
+            return None, None
+
+def main():
+    # 配置数据库连接参数
+    db_config = {
+        "host": "172.20.45.129",
+        "port": 4000,
+        "user": "root",
+        "password": "=PDT49#80Z!RVv52_z",
+        "database": "quality"
+    }
+
+    # 初始化组件
+
+    llm_client = LLMClient()
+    db_storage = MySQLStorage(**db_config)
+    # csv_file_path = 'news_site_liantong.xlsx'
+    csv_file_path_special = 'news_site_liantong_area.xlsx'
+    try:
+        # 连接数据库
+        db_storage.connect()
+        # db_storage.create_table()
+
+        # 测试用例
+        # target_sheets = None
+        # db_storage.import_from_excel(llm_client,db_storage,csv_file_path,target_sheets)
+        db_storage.import_special_site_from_excel(llm_client,db_storage,csv_file_path_special)
+
+    except DatabaseError as e:
+        print(f"数据库错误: {str(e)}")
+    except Exception as e:
+        print(f"主程序错误: {str(e)}")
+    finally:
+        # 关闭数据库连接
+        db_storage.disconnect()
+        print("数据库连接已关闭")
+
+
+if __name__ == '__main__':
+    main()

+ 154 - 0
tools/联通项目/覆盖率原始站点入库.py

@@ -0,0 +1,154 @@
+import csv
+import pymysql
+
+# 数据库连接配置
+db_config = {
+    "host": "172.20.45.129",
+    "port": 4000,
+    "user": "root",
+    "password": "=PDT49#80Z!RVv52_z",
+    "database": "quality"
+}
+
+# 根据实际CSV列名调整映射
+field_mapping = {
+    '网站名': 'original_site_name',
+    '剑鱼收录站点名': 'swordfish_site_name',
+    '重点网站': 'is_key_site',
+    '验证栏目是否收录全': 'is_full_coverage',
+    '是否需要登录': 'requires_login',
+    '收录情况-人工': 'coverage_status',
+    '是否无效站点0无效,1有效': 'is_valid_site',
+    '僵尸站点':'zombie_site',
+    '注册不了站点':'unregister_site'
+}
+
+
+def convert_bool(value):
+    """将中文布尔值转换为数据库中的0/1"""
+    if not value or str(value).strip() == '':
+        return None
+    value = str(value).strip()
+    if value == '是' or '是' in value:
+        return 1
+    elif value == '否':
+        return 0
+    return None
+
+
+def process_csv_row(row):
+    """处理CSV行数据,转换为数据库格式"""
+    processed = {}
+    for csv_field, db_field in field_mapping.items():
+        # 获取原始值
+        raw_value = row.get(csv_field, '')
+
+        # 处理值
+        if raw_value is None or str(raw_value).strip() == '':
+            value = None
+        else:
+            value = str(raw_value).strip()
+
+        # 布尔字段特殊处理
+        if db_field in ['is_key_site', 'requires_login']:
+            processed[db_field] = convert_bool(value)
+        elif db_field == 'is_valid_site':
+            # 处理是否无效站点字段
+            if value is None:
+                processed[db_field] = 1  # 默认有效
+            elif value.isdigit():
+                processed[db_field] = int(value)
+            else:
+                processed[db_field] = 1  # 默认有效
+        elif db_field == 'zombie_site':
+            # 处理是否僵尸站点字段
+            if value is None:
+                processed[db_field] = 1  # 默认有效
+            elif value.isdigit():
+                processed[db_field] = int(value)
+            else:
+                processed[db_field] = 1  # 默认有效
+        elif db_field == 'unregister_site':
+            # 处理是否僵尸站点字段
+            if value is None:
+                processed[db_field] = 1  # 默认有效
+            elif value.isdigit():
+                processed[db_field] = int(value)
+            else:
+                processed[db_field] = 1  # 默认有效
+        else:
+            processed[db_field] = value
+
+    # 特殊逻辑:如果收录情况包含特定文本,标记为无效
+    if processed.get('coverage_status'):
+        if '网站失效' in processed['coverage_status'] or '网站已作废' in processed['coverage_status']:
+            processed['is_valid_site'] = 0
+
+    return processed
+
+
+def import_csv_to_mysql(csv_file_path):
+    """将CSV数据导入MySQL数据库"""
+    try:
+        # 连接数据库
+        connection = pymysql.connect(**db_config)
+        cursor = connection.cursor()
+
+        # 读取CSV文件
+        with open(csv_file_path, 'r', encoding='utf-8-sig') as csvfile:
+            # 明确指定分隔符为逗号
+            reader = csv.DictReader(csvfile, delimiter=',')
+
+            for row in reader:
+                if not row:  # 跳过空行
+                    continue
+
+                data = process_csv_row(row)
+
+                # 构建SQL插入语句
+                sql = """
+                INSERT INTO site_records_liantong (
+                    original_site_name, swordfish_site_name, is_key_site, 
+                    is_full_coverage, requires_login, coverage_status, is_valid_site,zombie_site,unregister_site
+                ) VALUES (%s, %s, %s, %s, %s, %s, %s,%s,%s)
+                """
+
+                # 执行插入
+                cursor.execute(sql, (
+                    data['original_site_name'],
+                    data['swordfish_site_name'] or data['original_site_name'],  # 为空时使用原网站名
+                    data['is_key_site'] if data['is_key_site'] is not None else 0,
+                    data['is_full_coverage'] if data['is_full_coverage'] is not None else 0,
+                    data['requires_login'] if data['requires_login'] is not None else 0,
+                    data['coverage_status'],
+                    data['is_valid_site'],
+                    data['zombie_site'],
+                    data['unregister_site']
+                ))
+
+        # 提交事务
+        connection.commit()
+        print(f"成功导入 {cursor.rowcount} 条记录")
+
+    except Exception as e:
+        print(f"导入数据时出错: {str(e)}")
+        if 'connection' in locals():
+            connection.rollback()
+    finally:
+        if 'cursor' in locals():
+            cursor.close()
+        if 'connection' in locals():
+            connection.close()
+
+
+if __name__ == "__main__":
+    # 替换为您的CSV文件路径
+    csv_file_path = 'sites_data.csv'
+
+    # 先打印前几行数据用于验证
+    with open(csv_file_path, 'r', encoding='utf-8-sig') as f:
+        for _ in range(5):
+            print(repr(next(f)))
+
+    # 执行导入
+    import_csv_to_mysql(csv_file_path)