wcc há 3 semanas atrás
pai
commit
307b1e1c2d

+ 47 - 0
bidding_test/bidd.go

@@ -19,6 +19,53 @@ import (
 	"time"
 )
 
+// exportBidding exportBidding
+func exportBidding() {
+	MgoB = &mongodb.MongodbSim{
+		MongodbAddr: "172.31.31.202:27081,172.20.45.128:27080",
+		//MongodbAddr: "127.0.0.1:27083",
+		Size:     10,
+		DbName:   "qfw",
+		UserName: "SJZY_RWbid_ES",
+		Password: "SJZY@B4i4D5e6S",
+		//Direct:      true,
+	}
+	MgoB.InitPool()
+
+	sess := MgoB.GetMgoConn()
+	defer MgoB.DestoryMongoConn(sess)
+	where := map[string]interface{}{
+		"subtype": "开标记录",
+	}
+	query := sess.DB("qfw").C("bidding").Find(where).Select(map[string]interface{}{"title": 1, "channel": 1, "detail": 1, "comeintime": 1, "extracttype": 1, "infoformat": 1}).Iter()
+	count := 0
+
+	ch := make(chan bool, 20)
+	wg := &sync.WaitGroup{}
+
+	for tmp := make(map[string]interface{}); query.Next(tmp); count++ {
+		if count%10000 == 0 {
+			log.Println("current:", count)
+		}
+
+		ch <- true
+		wg.Add(1)
+
+		go func(tmp map[string]interface{}) {
+			defer func() {
+				<-ch
+				wg.Done()
+			}()
+			MgoB.SaveByOriID("wcc_bidding_kaibiao", tmp)
+		}(tmp)
+
+		tmp = make(map[string]interface{})
+	}
+
+	wg.Wait()
+	log.Println("处理完毕")
+}
+
 func getBidding0311() {
 	// 3. 构造 MongoDB 查询
 	filter := bson.M{

BIN
bidding_test/exportBidding


+ 3 - 1
bidding_test/main.go

@@ -90,8 +90,10 @@ func InitEs() {
 }
 
 func main() {
-	countReportYear22()
+	exportBidding()
 	log.Println("数据处理完毕")
+
+	return
 	//InitMgo()
 	//InitEs()
 	//

+ 108 - 10
environment/company_type.go

@@ -2,9 +2,70 @@ package main
 
 import (
 	util "jygit.jydev.jianyu360.cn/data_processing/common_utils"
+	"log"
+	"regexp"
 	"strings"
 )
 
+// getCodeType 根据企业名称,获取经营主体代码标签
+func getCodeType(name string) (tab1, tab2 string) {
+	where := map[string]interface{}{
+		"use_flag": 0,
+		"company_status": map[string]interface{}{
+			"$nin": []string{"注销", "吊销", "吊销,已注销"},
+		},
+		"company_name": name,
+	}
+
+	// 🔍 正则,用于提取4位数字
+	re4 := regexp.MustCompile(`\d{4}`)
+
+	top_bases, _ := Mgo181.FindOne("company_base", where)
+	company_type := util.ObjToString((*top_bases)["company_type"])
+	// 去除引号
+	cleanText := strings.ReplaceAll(company_type, `"`, "")
+	cleanText = strings.TrimSpace(cleanText)
+	// 替换中文括号为英文括号
+	cleanText = strings.ReplaceAll(cleanText, "(", "(")
+	cleanText = strings.ReplaceAll(cleanText, ")", ")")
+	cleanText = strings.ReplaceAll(cleanText, "外资比例低于25%", "")
+
+	// 判断是不是日期(如 2008/10/31)
+	if matched, _ := regexp.MatchString(`^\d{4}/\d{1,2}/\d{1,2}$`, cleanText); matched {
+		log.Printf("跳过日期行: %s", cleanText)
+		return
+	}
+	// 如果包含“年”/“月”/“日”等,也跳过(不提取数字)
+	if strings.Contains(cleanText, "年") || strings.Contains(cleanText, "月") || strings.Contains(cleanText, "日") {
+		log.Printf("跳过含日期描述的行: %s", cleanText)
+		return
+	}
+
+	var code string
+	// 优先提取4位数字
+	if m := re4.FindString(cleanText); m != "" {
+		code = m
+	} else {
+		// 去除引号后完全匹配
+		if c, ok := codeMap[cleanText]; ok {
+			code = c
+		}
+	}
+
+	if code == "" {
+		code = getCodeByCompanyType(cleanText, codeMap)
+		if code != "" {
+			tab1 = codeZhu[code]
+			tab2 = codeZhu2[code]
+		}
+	} else {
+		tab1 = codeZhu[code]
+		tab2 = codeZhu2[code]
+	}
+
+	return
+}
+
 // getCompanyType 获取公司类型;央企、国企、央企下属、事业单位、民企
 func getCompanyType(name string) (company_type string) {
 	if name == "" {
@@ -38,26 +99,55 @@ func getCompanyType(name string) (company_type string) {
 		return
 	}
 
+	//special_social_organ 社会团体
+	soc, _ := Mgo181.FindOne("special_social_organ", where)
+	if soc != nil && (len(*soc)) > 0 {
+		company_type = "社会团体"
+		return
+	}
+
 	//company_base
 	where["use_flag"] = 0
 	bases, _ := Mgo181.Find("company_base", where, nil, nil, false, -1, -1)
 	if bases != nil && (len(*bases)) > 0 {
 		for _, v := range *bases {
-			if strings.Contains(util.ObjToString(v["company_status"]), "吊销") || strings.Contains(util.ObjToString(v["company_status"]), "注销") {
+			if strings.Contains(util.ObjToString(v["company_status"]), "吊销") || strings.Contains(util.ObjToString(v["company_status"]), "注销") || util.ObjToString((v)["company_type"]) == "" {
 				continue
 			} else {
+
 				bty := util.ObjToString((v)["company_type"])
 				if strings.Contains(bty, "国有独资") || strings.Contains(bty, "国有控股") ||
 					bty == "全民所有制" || bty == "集体所有制" || bty == "全民所有制分支机构(非法人)" ||
-					bty == "集体分支机构(非法人)" {
+					bty == "集体分支机构(非法人)" || bty == "内资集团" || bty == "国有事业单位营业" || bty == "集体事业单位营业" ||
+					bty == "国有社团法人营业" || bty == "国有经营单位(非法人)" || bty == "集体经营单位(非法人)" {
 					company_type = "国企"
 					return
 				}
+				// 地方国企
+				par_name := getTop(name)
+				topwhere := map[string]interface{}{
+					"use_flag": 0,
+					"company_status": map[string]interface{}{
+						"$nin": []string{"注销", "吊销", "吊销,已注销"},
+					},
+					"company_name": par_name,
+				}
+
+				top_bases, _ := Mgo181.FindOne("company_base", topwhere)
+				top_company_type := util.ObjToString((*top_bases)["company_type"])
+
+				if strings.Contains(top_company_type, "国有独资") || strings.Contains(top_company_type, "国有控股") ||
+					top_company_type == "全民所有制" || top_company_type == "集体所有制" || top_company_type == "全民所有制分支机构(非法人)" ||
+					top_company_type == "集体分支机构(非法人)" || top_company_type == "内资集团" || top_company_type == "国有事业单位营业" || top_company_type == "集体事业单位营业" ||
+					top_company_type == "国有社团法人营业" || top_company_type == "国有经营单位(非法人)" || top_company_type == "集体经营单位(非法人)" || top_company_type == "事业单位" {
+					company_type = "地方国企"
+					return
+				}
 			}
 		}
 	}
 
-	company_type = "民企"
+	//company_type = "民企"
 	return
 }
 
@@ -94,6 +184,7 @@ func getMarketType(name string) (stype string) {
 	return
 }
 
+// getTop 获取最上级公司
 // getTop 获取最上级公司
 func getTop(name string) (top string) {
 	if name == "" {
@@ -102,6 +193,9 @@ func getTop(name string) (top string) {
 
 	currName := name
 	firstSearch := true
+	visited := make(map[string]bool)
+	visited[currName] = true
+
 	for {
 		topTmp := getParentsByPartner(currName)
 		topName := util.ObjToString(topTmp["stock_name"])
@@ -109,24 +203,28 @@ func getTop(name string) (top string) {
 		// 第一次查找就失败,直接返回空
 		if firstSearch && topName == "" {
 			return
-		} else {
-			firstSearch = false
 		}
+		firstSearch = false
 
 		// 非第一次查找,上级为空,返回当前获取到的上级
-		if !firstSearch && topName == "" {
+		if topName == "" {
 			return currName
 		}
 
-		if !firstSearch && !strings.Contains(topName, "公司") {
+		// 避免循环:如果 topName 与 currName 相同,或 topName 已访问过,说明进入环路
+		if topName == currName || visited[topName] {
 			return currName
 		}
 
-		currName = topName
+		// 如果 topName 不符合要求,比如不含“公司”,也返回当前
+		if !strings.Contains(topName, "公司") {
+			return currName
+		}
 
+		// 更新当前公司名,继续向上找
+		currName = topName
+		visited[currName] = true
 	}
-
-	return
 }
 
 // getParentsByPartner 获取母公司,投资比例 50% 以上

+ 2 - 1
environment/config.toml

@@ -30,7 +30,8 @@
 
 
 [env]
-    file = "./data.xlsx" ## 读取文件
+#    file = "./data.xlsx" ## 读取文件
+    file = "./首创企业类型.xlsx" ## 读取文件
     sheet= "Sheet1" ## 默认读取数据在Sheet1
 
 

BIN
environment/environment


+ 97 - 27
environment/init.go

@@ -5,14 +5,18 @@ import (
 	"github.com/xuri/excelize/v2"
 	"jygit.jydev.jianyu360.cn/data_processing/common_utils/mongodb"
 	"log"
+	"strings"
 )
 
 var (
-	yangMap      = make(map[string]bool) //存储98家央企
-	yangChildMap = make(map[string]bool) //存储央企 下属子公司
-	Mgo181       *mongodb.MongodbSim     //
-	MgoB         *mongodb.MongodbSim     //
-	MgoP         *mongodb.MongodbSim     //
+	yangMap      = make(map[string]bool)   //存储98家央企
+	yangChildMap = make(map[string]bool)   //存储央企 下属子公司
+	codeZhu      = make(map[string]string) //内外个私农合 标签
+	codeZhu2     = make(map[string]string) //国企、外企、私企
+	codeMap      = make(map[string]string) //code-企业类型
+	Mgo181       *mongodb.MongodbSim       //
+	MgoB         *mongodb.MongodbSim       //
+	MgoP         *mongodb.MongodbSim       //
 	GF           GlobalConf
 )
 
@@ -46,27 +50,27 @@ func InitMgo() {
 		Direct:      GF.Mongo181.Direct,
 	}
 	Mgo181.InitPool()
-	MgoP = &mongodb.MongodbSim{
-		MongodbAddr: GF.MongoP.Host,
-		Size:        10,
-		DbName:      GF.MongoP.DB,
-		UserName:    GF.MongoP.Username,
-		Password:    GF.MongoP.Password,
-		Direct:      GF.MongoP.Direct,
-	}
-
-	MgoP.InitPool()
-
-	MgoB = &mongodb.MongodbSim{
-		MongodbAddr: GF.MongoB.Host,
-		Size:        10,
-		DbName:      GF.MongoB.DB,
-		UserName:    GF.MongoB.Username,
-		Password:    GF.MongoB.Password,
-		Direct:      GF.MongoB.Direct,
-	}
+	//MgoP = &mongodb.MongodbSim{
+	//	MongodbAddr: GF.MongoP.Host,
+	//	Size:        10,
+	//	DbName:      GF.MongoP.DB,
+	//	UserName:    GF.MongoP.Username,
+	//	Password:    GF.MongoP.Password,
+	//	Direct:      GF.MongoP.Direct,
+	//}
+	//
+	//MgoP.InitPool()
 
-	MgoB.InitPool()
+	//MgoB = &mongodb.MongodbSim{
+	//	MongodbAddr: GF.MongoB.Host,
+	//	Size:        10,
+	//	DbName:      GF.MongoB.DB,
+	//	UserName:    GF.MongoB.Username,
+	//	Password:    GF.MongoB.Password,
+	//	Direct:      GF.MongoB.Direct,
+	//}
+	//
+	//MgoB.InitPool()
 }
 
 // readXlsx 读取央企
@@ -90,15 +94,81 @@ func readXlsx() {
 			yangMap[name] = true
 		}
 	}
+	log.Println("央企数量", len(yangMap))
 	// 央企下属
-	rows2, err := f.GetRows("Sheet2")
+	rows2, err := f.GetRows("Sheet3")
 	if err != nil {
 		log.Fatal("❌ 无法读取 Sheet2:", err)
 	}
 	for i := 1; i < len(rows2); i++ {
-		name := rows2[i][1]
+		row := rows2[i]
+		if len(row) == 0 {
+			continue
+		}
+		name := rows2[i][0]
 		if name != "" {
 			yangChildMap[name] = true
 		}
 	}
+	log.Println("央企下属数量", len(yangChildMap))
+}
+
+//func readXlsx2() {
+//	filePath := "企业经营主体代码表.xlsx"
+//	// 1. 读取 Excel(获取 A 列数据)
+//	f, err := excelize.OpenFile(filePath)
+//	if err != nil {
+//		log.Fatal("❌ 无法打开 Excel 文件:", err)
+//	}
+//	defer f.Close()
+//
+//	//读取央企
+//	rows, err := f.GetRows("市场主体类型代码")
+//	if err != nil {
+//		log.Fatal("❌ 无法读取 Sheet1:", err)
+//	}
+//	for i := 1; i < len(rows); i++ {
+//		code := strings.TrimSpace(rows[i][2])
+//		name := strings.TrimSpace(rows[i][3])
+//		name = strings.ReplaceAll(name, "(", "(")
+//		name = strings.ReplaceAll(name, ")", ")")
+//		codeMap[name] = code
+//		tab1 := strings.TrimSpace(rows[i][4])
+//		tab2 := strings.TrimSpace(rows[i][6])
+//		codeZhu[code] = tab1
+//		codeZhu2[code] = tab2
+//	}
+//
+//	log.Println("readXlsx2", "企业经营主体代码表 处理完毕")
+//}
+
+func readXlsx2() {
+	filePath := "法人类型代码表.xlsx"
+	// 1. 读取 Excel(获取 A 列数据)
+	f, err := excelize.OpenFile(filePath)
+	if err != nil {
+		log.Fatal("❌ 无法打开 Excel 文件:", err)
+	}
+	defer f.Close()
+
+	//读取央企
+	rows, err := f.GetRows("市场主体类型代码-叶子节点")
+	if err != nil {
+		log.Fatal("❌ 无法读取 市场主体类型代码-叶子节点:", err)
+	}
+	for i := 2; i < len(rows); i++ {
+		if len(rows[i]) < 16 {
+			continue
+		}
+		code := strings.TrimSpace(rows[i][4])
+		name := strings.TrimSpace(rows[i][5])
+		name = strings.ReplaceAll(name, "(", "(")
+		name = strings.ReplaceAll(name, ")", ")")
+		codeMap[name] = code
+		tab1 := strings.TrimSpace(rows[i][15])
+		codeZhu[code] = tab1
+
+	}
+
+	log.Println("readXlsx2", "企业经营主体代码表 处理完毕")
 }

+ 27 - 9
environment/main.go

@@ -8,6 +8,7 @@ import (
 	"jygit.jydev.jianyu360.cn/data_processing/common_utils/mongodb"
 	"log"
 	"net/http"
+	"strings"
 )
 
 type EnvRequest struct {
@@ -27,7 +28,8 @@ func main() {
 		return
 	}
 
-	readXlsx() //98家 央企名单
+	readXlsx()  //98家 央企名单
+	readXlsx2() //企业经营主体代码表
 	InitMgo()
 	//getCompanyTypes()
 	updateXlsx()
@@ -56,20 +58,36 @@ func updateXlsx() {
 	}
 	for i := 1; i < len(rows); i++ {
 		//project_name := rows[i][0] //项目名称
-		name := rows[i][1] //企业名称
+		name := rows[i][0] //企业名称
+		name = strings.TrimSpace(name)
 		res1 := getCompanyType(name)
-		res2 := getMarketType(name)
-		res3 := getTop(name)
-
 		if res1 != "" {
 			f.SetCellValue(GF.Env.Sheet, fmt.Sprintf("D%v", i+1), res1)
 		}
-		if res2 != "" {
-			f.SetCellValue(GF.Env.Sheet, fmt.Sprintf("E%v", i+1), res2)
+		//res2 := getMarketType(name)
+		//if res2 != "" {
+		//	f.SetCellValue(GF.Env.Sheet, fmt.Sprintf("E%v", i+1), res2)
+		//}
+		//res3 := getTop(name)
+		//if res3 != "" {
+		//	f.SetCellValue(GF.Env.Sheet, fmt.Sprintf("F%v", i+1), res3)
+		//}
+
+		tab1, tab2 := getCodeType(name)
+		if res1 == "" {
+			if tab1 == "私企" || tab1 == "个体" {
+				f.SetCellValue(GF.Env.Sheet, fmt.Sprintf("D%v", i+1), "民企")
+			}
 		}
-		if res3 != "" {
-			f.SetCellValue(GF.Env.Sheet, fmt.Sprintf("F%v", i+1), res3)
+		if tab1 != "" {
+			f.SetCellValue(GF.Env.Sheet, fmt.Sprintf("G%v", i+1), tab1)
+		}
+		if tab2 != "" {
+			f.SetCellValue(GF.Env.Sheet, fmt.Sprintf("H%v", i+1), tab2)
 		}
+
+		log.Println(name, res1, tab1, tab2)
+
 	}
 	f.Save()
 }

+ 258 - 0
environment/utils.go

@@ -1,5 +1,11 @@
 package main
 
+import (
+	"log"
+	"regexp"
+	"strings"
+)
+
 // getProject 根据标讯ID获取项目信息
 func getProject(id string) map[string]interface{} {
 	where := map[string]interface{}{
@@ -10,3 +16,255 @@ func getProject(id string) map[string]interface{} {
 
 	return project
 }
+
+// getCodeByCompanyType  根据企业类型,返回经营主体代码
+func getCodeByCompanyType(cleanText string, codeMap map[string]string) (code string) {
+	if code == "" {
+		//一人有限责任公司
+		if strings.Contains(cleanText, "一人有限责任公司分公司") {
+			cleanText = "一人有限责任公司分公司"
+		} else if strings.Contains(cleanText, "一人有限责任公司") {
+			cleanText = "一人有限责任公司"
+		} else if cleanText == "有限责任(公司)" {
+			cleanText = "有限责任公司"
+		} else if cleanText == "上市股份有限公司分公司" {
+			cleanText = "股份有限公司分公司(上市)"
+		} else if cleanText == "上市股份有限公司分公司(非上市)" {
+			cleanText = "股份有限公司分公司(非上市)"
+		} else if !strings.Contains(cleanText, "非个人") && !strings.Contains(cleanText, "非个体") {
+			if strings.Contains(cleanText, "个人") || strings.Contains(cleanText, "个体") || strings.Contains(cleanText, "户体商工个") {
+				cleanText = "个体工商户"
+			}
+		} else if strings.Contains(cleanText, "中外合作") { // 中外合作企业 - 有限责任公司(中外合作)
+			if strings.Contains(cleanText, "非公司外商投资企业(中外合作)") {
+				cleanText = "非公司外商投资企业(中外合作)"
+			} else {
+				cleanText = "有限责任公司(中外合作)"
+			}
+		} else if strings.Contains(cleanText, "有限责任公司(中外合资)") { //有限责任公司(中外合资)
+			cleanText = "有限责任公司(中外合资)"
+		} else if strings.Contains(cleanText, "外商投资企业分支机构") { //非公司外商投资企业分支机构;外商投资企业分支机构
+			if strings.Contains(cleanText, "非公司") {
+				cleanText = "非公司外商投资企业分支机构"
+			} else {
+				cleanText = "外商投资企业分支机构"
+			}
+		} else if strings.Contains(cleanText, "其他") {
+			//有限责任公司(港、澳、台)
+			if strings.Contains(cleanText, "港、澳、台") {
+				if strings.Contains(cleanText, "有限责任公司") {
+					cleanText = "有限责任公司(港、澳、台)"
+				} else if strings.Contains(cleanText, "非公司") {
+					code = "6300"
+					cleanText = "非公司"
+				}
+			}
+		} else if strings.Contains(cleanText, "有限责任公司(台港澳与境内合作)") {
+			cleanText = "有限责任公司(台港澳与境内合作)"
+		} else if strings.Contains(cleanText, "有限责任公司(台港澳与境内合资)") {
+			cleanText = "有限责任公司(台港澳与境内合资)"
+		} else if strings.Contains(cleanText, "有限责任公司(台港澳与外国投资者合资)") {
+			cleanText = "有限责任公司(台港澳与外国投资者合资)"
+		} else if strings.Contains(cleanText, "有限责任公司(台港澳合资)") || (strings.Contains(cleanText, "台、港、澳资") && strings.Contains(cleanText, "有限责任公司")) {
+			cleanText = "有限责任公司(台港澳合资)"
+		} else if strings.Contains(cleanText, "有限责任公司(台港澳法人独资)") {
+			cleanText = "有限责任公司(港澳台法人独资)"
+		} else if strings.Contains(cleanText, "有限责任公司(台港澳自然人独资)") {
+			cleanText = "有限责任公司(港澳台自然人独资)"
+		} else if strings.Contains(cleanText, "有限责任公司(外商合资)") {
+			cleanText = "有限责任公司(外商合资)"
+		} else if strings.Contains(cleanText, "有限责任公司(外商投资") {
+			cleanText = "有限责任公司(外商投资、非独资)"
+		} else if strings.Contains(cleanText, "有限责任公司(外国法人独资)") {
+			cleanText = "有限责任公司(外国法人独资)"
+		} else if strings.Contains(cleanText, "外国非法人经济组织独资") {
+			cleanText = "外国非法人经济组织独资"
+		} else if strings.Contains(cleanText, "有限责任公司(外国自然人独资)") || strings.Contains(cleanText, "有限责任公司(外自然人独资)") {
+			cleanText = "有限责任公司(外国自然人独资)"
+		} else if strings.Contains(cleanText, "有限责任公司(法人独资)(外商投资企业投资)") {
+			cleanText = "有限责任公司分公司(外商投资企业法人独资)"
+		} else if strings.Contains(cleanText, "有限责任公司(港、澳、台)") || strings.Contains(cleanText, "有限责任公司(港澳台合资)") {
+			cleanText = "有限责任公司(台港澳合资)"
+		} else if strings.Contains(cleanText, "有限责任公司") || strings.Contains(cleanText, "港澳台与境内合作") {
+			cleanText = "有限责任公司(台港澳与境内合作)"
+		} else if strings.Contains(cleanText, "港澳台与境内合资") && strings.Contains(cleanText, "有限责任公司") {
+			cleanText = "有限责任公司(台港澳与境内合资)"
+		} else
+		// 这个需要和贾老师确认
+		if strings.Contains(cleanText, "有限责任公司(法人独资") && strings.Contains(cleanText, "私营") {
+			cleanText = "有限责任公司(非自然人投资或控股的法人独资)"
+		} else if strings.Contains(cleanText, "港澳台与外国投资者合资") && strings.Contains(cleanText, "有限责任公司") {
+			cleanText = "有限责任公司(台港澳与外国投资者合资)"
+		} else if strings.Contains(cleanText, "港澳台法人独资") && strings.Contains(cleanText, "有限责任公司") {
+			cleanText = "有限责任公司(港澳台法人独资)"
+		} else if strings.Contains(cleanText, "港澳台自然人独资") && strings.Contains(cleanText, "有限责任公司") {
+			cleanText = "有限责任公司(港澳台自然人独资)"
+		} else if strings.Contains(cleanText, "有限责任公司(港澳台非法人经济组织独资)") {
+			cleanText = "有限责任公司(台港澳非法人经济组织独资)"
+		} else if strings.Contains(cleanText, "港澳台投资、非独资") && strings.Contains(cleanText, "有限责任公司") {
+			cleanText = "有限责任公司(港澳台投资、非独资)"
+		} else if strings.Contains(cleanText, "港澳台合资") && strings.Contains(cleanText, "未上市") {
+			if strings.Contains(cleanText, "股份有限公司") {
+				code = "6230"
+			}
+		} else if strings.Contains(cleanText, "集体所有制") {
+			cleanText = "集体所有制"
+		} else if strings.Contains(cleanText, "国有独资") {
+			if strings.Contains(cleanText, "有限责公司分公司") {
+				cleanText = "有限责任公司分公司(国有独资)"
+			} else if strings.Contains(cleanText, "有限责公司") {
+				cleanText = "有限责任公司(国有独资)"
+			}
+		} else
+		//台、港、澳
+		if strings.Contains(cleanText, "台、港、澳") {
+			if strings.Contains(cleanText, "台、港、澳分公司") || strings.Contains(cleanText, "台、港、澳投资企业分公司") || strings.Contains(cleanText, "台、港、澳投资公司分公司") {
+				code = "6810"
+			}
+			if strings.Contains(cleanText, "台、港、澳办事处") {
+				code = "6830"
+			}
+			if strings.Contains(cleanText, "台、港、澳投资企业") {
+				code = "6000"
+			}
+			if strings.Contains(cleanText, "台、港、澳投资企业其他") {
+				code = "6190"
+			}
+		} else if cleanText == "股份有限公司分支机构(台港澳与境内合资)" {
+			code = "6220"
+		} else if strings.Contains(cleanText, "台港澳投资企业办事处") {
+			code = "6830"
+		} else if strings.Contains(cleanText, "台港澳投资有限合伙企业") {
+			code = "6400"
+		} else if strings.Contains(cleanText, "台港澳投资普通合伙企业分支机构") {
+			code = "6840"
+		} else if strings.Contains(cleanText, "台港澳投资特殊普通合伙企业分支机构") {
+			code = "6420"
+		} else if strings.Contains(cleanText, "台港澳股份有限公司") {
+			code = "6200"
+		} else if strings.Contains(cleanText, "台港澳非公司") {
+			code = "6300"
+		} else if cleanText == "国外投资" {
+			code = "5000"
+		} else if strings.Contains(cleanText, "国有事业单位营业") {
+			cleanText = "国有事业单位营业"
+		} else if strings.Contains(cleanText, "国有控股") {
+			if strings.Contains(cleanText, "非上市") {
+				if strings.Contains(cleanText, "股份有限公司分公司") {
+					code = "1223"
+				}
+			} else if strings.Contains(cleanText, "上市") {
+				if strings.Contains(cleanText, "股份有限公司分公司") {
+					code = "2213"
+					cleanText = "股份有限公司分公司(上市、国有控股)"
+				}
+			} else if strings.Contains(cleanText, "股份有限公司分公司") {
+				code = "2223"
+			} else if strings.Contains(cleanText, "有限责任公司分公司") {
+				code = "2140"
+			} else if strings.Contains(cleanText, "有限责任公司") {
+				code = "1140"
+			}
+		} else if strings.Contains(cleanText, "国有") {
+			if strings.Contains(cleanText, "经营单位") && strings.Contains(cleanText, "非法人") {
+				code = "4410"
+				cleanText = "国有经营单位(非法人)"
+			} else if strings.Contains(cleanText, "国有联营") {
+				code = "4600"
+			}
+		} else
+		//合伙企业
+		if strings.Contains(cleanText, "合伙企业") {
+			if strings.Contains(cleanText, "特殊普通合伙") {
+				code = "4532"
+			} else if strings.Contains(cleanText, "普通合伙") {
+				code = "4530"
+			} else if strings.Contains(cleanText, "有限合伙") {
+				code = "4533"
+			} else if strings.Contains(cleanText, "合伙企业分支机构") {
+				code = "4550"
+			}
+		} else if strings.Contains(cleanText, "合伙私营企业") {
+			code = "4530"
+		} else if cleanText == "内资企业法人联营" {
+			cleanText = "联营"
+		} else
+		//农民专业合作社分支机构
+		if strings.Contains(cleanText, "合作社") {
+			if strings.Contains(cleanText, "农民专业合作社分支机构") {
+				cleanText = "农民专业合作社分支机构"
+			} else if strings.Contains(cleanText, "农民专业合作社") {
+				cleanText = "农民专业合作社"
+			} else if strings.Contains(cleanText, "合作社分支机构") {
+				cleanText = "农民专业合作社分支机构"
+			} else {
+				cleanText = "农民专业合作社"
+			}
+		} else if strings.Contains(cleanText, "非公司") {
+			if strings.Contains(cleanText, "港、澳、台投资企业分支机构") {
+				cleanText = "非公司台、港、澳投资企业分支机构"
+				code = "6820"
+			} else if strings.Contains(cleanText, "港、澳、台企业(港澳台合资)") {
+				cleanText = "非公司台、港、澳企业(台港澳与境内合作)"
+				code = "6310"
+			} else if strings.Contains(cleanText, "非公司外商投资企业") && strings.Contains(cleanText, "其他") {
+				code = "5390"
+			}
+		} else if strings.Contains(cleanText, "股份有限公司(上市公司)") {
+			cleanText = "股份有限公司(上市)"
+			code = "1210"
+		} else if strings.Contains(cleanText, "股份有限公司(中外合资、上市)") {
+			cleanText = "股份有限公司(中外合资、上市)"
+			code = "5220"
+		} else if strings.Contains(cleanText, "股份有限公司(中外合资、未上市)") || strings.Contains(cleanText, "股份有限公司(中外合资,未上市)") {
+			cleanText = "股份有限公司(中外合资、未上市)"
+			code = "5210"
+		} else if cleanText == "股份有限公司(其他)" {
+			code = "5290"
+		} else if strings.Contains(cleanText, "股份有限公司(其他台港澳股份有限公司)") {
+			code = "6290"
+		} else if cleanText == "股份有限公司(台、港、澳资)" {
+			code = "6270"
+		} else if strings.Contains(cleanText, "股份有限公司(台港澳与境内合资、上市)") || strings.Contains(cleanText, "股份有限公司(台港澳与境内合资,上市)") {
+			cleanText = "股份有限公司(台港澳与境内合资、上市)"
+			code = "6220"
+		} else if strings.Contains(cleanText, "股份有限公司(台港澳与境内合资、未上市)") {
+			cleanText = "股份有限公司(台港澳与境内合资、未上市)"
+			code = "6210"
+		} else if strings.Contains(cleanText, "股份有限公司(台港澳与外国投资者合资、未上市)") {
+			cleanText = "股份有限公司(台港澳与外国投资者合资、未上市)"
+			code = "6250"
+		} else if strings.Contains(cleanText, "股份有限公司(台港澳合资、上市)") {
+			cleanText = "股份有限公司(台港澳合资、上市)"
+			code = "6240"
+		} else if strings.Contains(cleanText, "股份有限公司(台港澳合资、未上市)") {
+			cleanText = "股份有限公司(台港澳合资、未上市)"
+			code = "6230"
+		} else if cleanText == "股份有限公司(港、澳、台)" {
+			code = "6200"
+		} else {
+
+		}
+		// 判断是不是日期(如 2008/10/31)
+		if matched, _ := regexp.MatchString(`^\d{4}/\d{1,2}/\d{1,2}$`, cleanText); matched {
+			log.Printf("跳过日期行: %s", cleanText)
+			return
+		}
+		// 如果包含“年”/“月”/“日”等,也跳过(不提取数字)
+		if strings.Contains(cleanText, "年") || strings.Contains(cleanText, "月") || strings.Contains(cleanText, "日") {
+			log.Printf("跳过含日期描述的行: %s", cleanText)
+			return
+		}
+
+		cleanText = strings.TrimSpace(cleanText)
+		cleanText = strings.ReplaceAll(cleanText, "(", "(")
+		cleanText = strings.ReplaceAll(cleanText, ")", ")")
+		if code == "" {
+			if c, ok := codeMap[cleanText]; ok {
+				code = c
+			}
+		}
+	}
+
+	return code
+}

BIN
environment/企业经营主体代码表.xlsx


BIN
environment/央企.xlsx


BIN
environment/法人类型代码表.xlsx


BIN
environment/首创企业类型.xlsx


+ 1 - 1
hp/config.toml

@@ -13,7 +13,7 @@ username = "SJZY_RWbid_ES"
 password = "SJZY@B4i4D5e6S"
 
 [readfile] ## 读取的企业文件
-    path = "./78list.xlsx"
+    path = "./央企.xlsx"
 
 
 [env]

BIN
hp/hp-L0


BIN
hp/央企.xlsx


BIN
hp/导出数据/结果-2025.07.13 18.25.08.xlsx


+ 177 - 0
project_chuan/project.go

@@ -549,6 +549,183 @@ func removeDuplicates(arr []string) []string {
 	return result
 }
 
+// searchES24 添加分词查询
+func searchES24(client *elastic.Client, projectName, buyer2 string, scoreThreshold float64, maxResults int) ([]map[string]interface{}, error) {
+	fieldsToTry := []string{"projectname.pname", "title", "detail"}
+
+	filtersToTry := [][]elastic.Query{
+		{elastic.NewTermsQuery("subtype", "中标", "成交", "合同", "单一")},
+		{elastic.NewTermsQuery("toptype", "招标", "预告", "采购意向")},
+		{elastic.NewTermsQuery("toptype", "拟建")},
+	}
+
+	var allResults []*elastic.SearchHit
+	seenIDs := make(map[string]bool)
+
+	// ✅ Step 1: 精准查询
+	for _, field := range fieldsToTry {
+		if field == "detail" && len(allResults) > 0 {
+			break
+		}
+		for _, filter := range filtersToTry {
+			query := elastic.NewBoolQuery().
+				Must(elastic.NewMultiMatchQuery(projectName, field).Type("phrase")).
+				Filter(filter...)
+			fetchFields := elastic.NewFetchSourceContext(true).Include(
+				"id", "title", "projectname", "projectcode", "bidamount", "score",
+				"area", "city", "toptype", "subtype", "buyer", "budget", "buyerperson",
+				"buyertel", "s_winner", "winnertel", "agency", "publishtime")
+
+			searchResult, err := client.Search().
+				Index("bidding").
+				Query(query).
+				Size(70).
+				FetchSourceContext(fetchFields).
+				Do(context.Background())
+			if err != nil {
+				return nil, err
+			}
+
+			for _, hit := range searchResult.Hits.Hits {
+				if !seenIDs[hit.Id] {
+					seenIDs[hit.Id] = true
+					allResults = append(allResults, hit)
+				}
+			}
+			if len(allResults) >= maxResults {
+				break
+			}
+		}
+		if len(allResults) >= maxResults {
+			break
+		}
+	}
+
+	// ✅ Step 2: 如果没结果,用分词兜底查询
+	if len(allResults) == 0 {
+		// 分词
+		analyzeResp, err := client.IndexAnalyze().
+			Index("bidding").
+			Analyzer("ik_smart").
+			Text(projectName).
+			Do(context.Background())
+		if err != nil {
+			return nil, fmt.Errorf("ik_smart analyze failed: %v", err)
+		}
+
+		var tokens []string
+		for _, token := range analyzeResp.Tokens {
+			tokens = append(tokens, token.Token)
+		}
+		if len(tokens) == 0 {
+			return nil, fmt.Errorf("no tokens found from ik_smart")
+		}
+
+		// 用所有分词一次性查询
+		queryText := strings.Join(tokens, " ")
+
+		for _, filter := range filtersToTry {
+			query := elastic.NewBoolQuery().
+				Must(
+					elastic.NewMultiMatchQuery(queryText, fieldsToTry...).
+						MinimumShouldMatch("100%"), // 必须包含所有分词,可根据需求改成 80%、50%
+				).
+				Filter(filter...)
+
+			searchResult, err := client.Search().
+				Index("bidding").
+				Query(query).
+				Size(10). // 根据需要调整
+				Do(context.Background())
+			if err != nil {
+				log.Warn("multi token query failed", zap.Error(err))
+				continue
+			}
+
+			for _, hit := range searchResult.Hits.Hits {
+				if !seenIDs[hit.Id] {
+					seenIDs[hit.Id] = true
+					allResults = append(allResults, hit)
+				}
+			}
+			if len(allResults) >= maxResults {
+				break
+			}
+		}
+	}
+
+	// ✅ Step 3: 后处理
+	var results []map[string]interface{}
+	seenProjectNames := make(map[string]bool)
+	seenProjectCodes := make(map[string]bool)
+	bidamountMap := make(map[float64]bool)
+
+	for _, hit := range allResults {
+		var doc map[string]interface{}
+		if err := json.Unmarshal(hit.Source, &doc); err != nil {
+			log.Info("解析文档失败", zap.Error(err))
+			continue
+		}
+
+		projectNameValue := util.ObjToString(doc["projectname"])
+		if projectNameValue == "" {
+			continue
+		}
+
+		projectCode := util.ObjToString(doc["projectcode"])
+		if projectCode != "" {
+			if seenProjectCodes[projectCode] {
+				continue
+			}
+			seenProjectCodes[projectCode] = true
+		}
+
+		bidamount := util.Float64All(doc["bidamount"])
+		if bidamount != 0 {
+			if bidamountMap[bidamount] {
+				continue
+			}
+			bidamountMap[bidamount] = true
+		}
+
+		score := *hit.Score
+		if score < scoreThreshold {
+			continue
+		}
+
+		id := util.ObjToString(doc["id"])
+		bidd, _ := MgoB.FindById("bidding", id, nil)
+		detail := util.ObjToString((*bidd)["detail"])
+
+		if detail != "" && !strings.Contains(detail, projectName) {
+			continue
+		}
+		if buyer2 != "" && !strings.Contains(detail, buyer2) {
+			continue
+		}
+
+		if seenProjectNames[projectNameValue] {
+			continue
+		}
+		seenProjectNames[projectNameValue] = true
+
+		doc["detail"] = detail
+		doc["score"] = score
+		results = append(results, doc)
+
+		if len(results) >= maxResults {
+			break
+		}
+	}
+
+	// ✅ Step 4: 排序
+	sort.Slice(results, func(i, j int) bool {
+		return util.Float64All(results[i]["score"]) > util.Float64All(results[j]["score"])
+	})
+
+	return results, nil
+}
+
 func searchES23(client *elastic.Client, projectName, buyer2 string, scoreThreshold float64, maxResults int) ([]map[string]interface{}, error) {
 	fieldsToTry := []string{"projectname.pname", "title", "detail"}
 

+ 2 - 2
project_chuan/project_test.go

@@ -71,7 +71,7 @@ func TestSearchES23(t *testing.T) {
 		log.Fatal("创建 Elasticsearch 客户端失败", zap.Error(err))
 	}
 
-	projectName := "奉贤区南竹港南水闸改建工程"
-	results, err := searchES23(client, projectName, "", 50, 50)
+	projectName := "赤壁市综合养老中心项目"
+	results, err := searchES24(client, projectName, "", 50, 50)
 	log.Info("aaa", zap.Any("results", results))
 }

+ 43 - 0
updateBidding/bidding.go

@@ -371,3 +371,46 @@ func updateBiddingBidamount() {
 
 	log.Info("数据处理完毕", log.Int("total", count))
 }
+
+// updateBiddingToptype 更新招标分类结果
+func updateBiddingToptype() {
+	defer util.Catch()
+	sess := MgoB.GetMgoConn()
+	defer MgoB.DestoryMongoConn(sess)
+
+	it := sess.DB("qfw").C("wcc_bidding_kaibiao").Find(nil).Select(nil).Sort("-_id").Iter()
+	count := 0
+
+	for tmp := make(map[string]interface{}); it.Next(&tmp); count++ {
+		if count%1000 == 0 {
+			log.Info("current", log.Int("count", count), log.Any("_id", tmp["_id"]))
+		}
+
+		biddingID := mongodb.BsonIdToSId(tmp["_id"])
+		update := make(map[string]interface{})
+
+		subtype := util.ObjToString(tmp["subtype"])
+		if subtype == "开标记录" {
+			continue
+		}
+
+		update["toptype"] = tmp["toptype"]
+		update["subtype"] = tmp["subtype"]
+
+		// 更新Es 数据
+		if len(update) > 0 {
+			//更新MongoDB
+			updatePool <- []map[string]interface{}{
+				{"_id": tmp["_id"]},
+				{"$set": update},
+			}
+			// 更新es
+			updateEsPool <- []map[string]interface{}{
+				{"_id": biddingID},
+				update,
+			}
+		}
+
+	}
+
+}

+ 12 - 0
updateBidding/lua_test.go

@@ -10,6 +10,18 @@ import (
 	"time"
 )
 
+func TestPing(t *testing.T) {
+
+	domain := "www.nbszzx.com.cn"
+
+	if checkURL(domain) {
+		fmt.Println("域名可访问")
+	} else {
+		fmt.Println("域名不可访问")
+	}
+
+}
+
 func TestUpdateLuaConfig(t *testing.T) {
 	//87 竞品
 	MgoLua := &mongodb.MongodbSim{

+ 183 - 1
updateBidding/luaconfig.go

@@ -1,17 +1,191 @@
 package main
 
 import (
+	"crypto/tls"
 	"fmt"
 	"github.com/xuri/excelize/v2"
 	util "jygit.jydev.jianyu360.cn/data_processing/common_utils"
 	"jygit.jydev.jianyu360.cn/data_processing/common_utils/mongodb"
 	"log"
 	"net"
+	"net/http"
 	"net/url"
 	"strings"
+	"sync"
 	"time"
 )
 
+// updatePing 更新ping 状态
+func updatePing() {
+	//87 竞品`
+	MgoLua := &mongodb.MongodbSim{
+		//MongodbAddr: "172.17.4.87:27080",
+		MongodbAddr: "127.0.0.1:27081",
+		Size:        10,
+		DbName:      "editor",
+		UserName:    "",
+		Password:    "",
+		Direct:      true,
+	}
+	MgoLua.InitPool()
+	sess := MgoLua.GetMgoConn()
+	defer MgoLua.DestoryMongoConn(sess)
+
+	ch := make(chan bool, 30)
+	wg := &sync.WaitGroup{}
+
+	where := map[string]interface{}{
+		"visit": "域名不可访问",
+	}
+	it := sess.DB("editor").C("wcc_code_test").Find(&where).Select(nil).Iter()
+	count := 0
+	for tmp := make(map[string]interface{}); it.Next(&tmp); count++ {
+		if count%100 == 0 {
+			log.Println("current:", count, tmp["domain"], tmp["code"])
+		}
+
+		ch <- true
+		wg.Add(1)
+		go func(tmp map[string]interface{}) {
+			defer func() {
+				<-ch
+				wg.Done()
+			}()
+
+			id := mongodb.BsonIdToSId(tmp["_id"])
+			domain := util.ObjToString(tmp["domain"])
+			update := make(map[string]interface{})
+			if checkURL(domain) {
+				update["visit"] = "域名可访问"
+			} else {
+				update["visit"] = "域名不可访问"
+			}
+
+			MgoLua.UpdateById("wcc_code_test", id, map[string]interface{}{"$set": update})
+
+		}(tmp)
+
+		tmp = make(map[string]interface{})
+	}
+	wg.Wait()
+	log.Println("数据处理完毕")
+}
+
+// checkURL 检查域名是否可访问
+func checkURL(domain string) bool {
+	// 打印 DNS 解析
+	//ips, err := net.LookupHost(domain)
+	//if err != nil {
+	//	fmt.Println("DNS 解析失败:", err)
+	//} else {
+	//	fmt.Println("Go 程序解析到的 IP:", ips)
+	//}
+	// 设置 HTTP 代理(走 Clash,本地端口根据实际情况改,比如 7890)
+	//proxyURL, _ := url.Parse("http://127.0.0.1:7897")
+	// 自定义 Transport:只用 IPv4,启用 HTTP/2
+	transport := &http.Transport{
+		//Proxy: http.ProxyURL(proxyURL),
+		DialContext: (&net.Dialer{
+			Timeout:   8 * time.Second,
+			DualStack: false, // 只用 IPv4
+		}).DialContext,
+		ForceAttemptHTTP2: true,
+		TLSClientConfig: &tls.Config{
+			InsecureSkipVerify: true, // 跳过证书验证
+		},
+	}
+
+	client := &http.Client{
+		Timeout:   60 * time.Second,
+		Transport: transport,
+	}
+
+	makeRequest := func(url string) bool {
+		req, _ := http.NewRequest("GET", url, nil)
+		// 浏览器常用头
+		req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)")
+		req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
+		req.Header.Set("Accept-Encoding", "gzip, deflate, br")
+		req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
+		req.Header.Set("Connection", "keep-alive")
+
+		start := time.Now()
+		resp, err := client.Do(req)
+		cost := time.Since(start)
+
+		if err != nil {
+			fmt.Println("访问", url, "失败:", err, "耗时:", cost)
+			return false
+		}
+		defer resp.Body.Close()
+		//fmt.Println("访问", url, "成功,状态码:", resp.StatusCode, "耗时:", cost)
+		return true
+	}
+
+	// 先 http,再 https
+	if makeRequest("http://" + domain) {
+		return true
+	}
+	if makeRequest("https://" + domain) {
+		return true
+	}
+	return false
+}
+
+func check(domain string) bool {
+	// DNS 用系统默认
+	ips, err := net.LookupHost(domain)
+	if err != nil {
+		fmt.Println("DNS 解析失败:", err)
+	} else {
+		fmt.Println("系统 DNS 解析到的 IP:", ips)
+	}
+
+	// 配置代理
+	proxyURL, _ := url.Parse("http://127.0.0.1:7897")
+	transport := &http.Transport{
+		Proxy:             http.ProxyURL(proxyURL),
+		ForceAttemptHTTP2: true,
+		// TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // 如果证书问题,可打开
+	}
+
+	client := &http.Client{
+		Timeout:   10 * time.Second,
+		Transport: transport,
+	}
+
+	makeRequest := func(url string) bool {
+		req, _ := http.NewRequest("GET", url, nil)
+		// 浏览器 header
+		req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)")
+		req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
+		req.Header.Set("Accept-Encoding", "gzip, deflate, br")
+		req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
+		req.Header.Set("Connection", "keep-alive")
+
+		start := time.Now()
+		resp, err := client.Do(req)
+		cost := time.Since(start)
+
+		if err != nil {
+			fmt.Println("访问", url, "失败:", err, "耗时:", cost)
+			return false
+		}
+		defer resp.Body.Close()
+		fmt.Println("访问", url, "成功,状态码:", resp.StatusCode, "耗时:", cost)
+		return true
+	}
+
+	// 先 http,再 https
+	if makeRequest("http://" + domain) {
+		return true
+	}
+	if makeRequest("https://" + domain) {
+		return true
+	}
+	return false
+}
+
 // pingDomain 测试域名可访问
 func pingDomain() {
 	//87 竞品`
@@ -60,7 +234,15 @@ func pingDomain() {
 				"i_state": tmp["i_state"],
 			}
 			timeout := 5 * time.Second
-			conn, err := net.DialTimeout("tcp", domain+":80", timeout)
+			// 判断 domain 是否包含端口
+			host, port, err := net.SplitHostPort(domain)
+			if err != nil {
+				// domain 本身没有带端口
+				host = domain
+				port = "80"
+			}
+
+			conn, err := net.DialTimeout("tcp", net.JoinHostPort(host, port), timeout)
 			if err != nil {
 				inser["visit"] = "域名不可访问"
 			} else {

+ 8 - 7
updateBidding/main.go

@@ -126,13 +126,12 @@ func Init() {
 }
 
 func main() {
-	pingDomain()
-
-	return
-	//Init()
+	//updatePing()
+	//return
+	Init()
 	//InitEsBiddingField()
-	//go updateMethod()   //更新mongodb
-	//go updateEsMethod() //更新es
+	go updateMethod()   //更新mongodb
+	go updateEsMethod() //更新es
 	//go updateEsMethodTest() // 更新测试环境ES
 	//go updateEsHrefMethod() //更新es href 字段
 	//go updateProjectEsMethod()
@@ -151,10 +150,12 @@ func main() {
 
 	//updateBiddingType() //更新标讯分类
 
-	//updateBiddingisValidFile()      //更新bidding isValidFile字段
+	//updateBiddingisValidFile() //更新bidding isValidFile字段
 	//updateBiddingTypeBySpidecode() //更新bidding ;根据spidecode 字段
 	//updateBiddingBasicClass() 	//更新 存量数据 basicClass 字段
 	//updateBiddingBasicClassTest() //更新测试环境 	basicClass 字段
+
+	updateBiddingToptype() // 更新招标分类结果
 	log.Info("over")
 	//c := make(chan bool, 1)
 	//<-c

BIN
updateBidding/updateBiddingToptype


+ 290 - 0
xlsx/181.go

@@ -7,11 +7,300 @@ import (
 	"go.mongodb.org/mongo-driver/bson"
 	"go.mongodb.org/mongo-driver/mongo"
 	"go.mongodb.org/mongo-driver/mongo/options"
+	util "jygit.jydev.jianyu360.cn/data_processing/common_utils"
+	"jygit.jydev.jianyu360.cn/data_processing/common_utils/mongodb"
 	"log"
 	"net/url"
 	"strings"
+	"time"
 )
 
+func get181Data() {
+	//181 凭安库
+	MgoQY := &mongodb.MongodbSim{
+		MongodbAddr: "172.17.4.181:27001",
+		//MongodbAddr: "127.0.0.1:27001",
+		DbName:   "mixdata",
+		Size:     10,
+		UserName: "",
+		Password: "",
+		//Direct:      true,
+	}
+	MgoQY.InitPool()
+	sess := MgoQY.GetMgoConn()
+	defer MgoQY.DestoryMongoConn(sess)
+
+	where := map[string]interface{}{
+		"use_flag": 0,
+		"company_status": map[string]interface{}{
+			"$nin": []string{"注销", "吊销", "吊销,已注销"},
+		},
+	}
+
+	selected := map[string]interface{}{
+		"company_name":   1,
+		"company_status": 1,
+		"company_type":   1,
+		"use_flag":       1,
+	}
+	query := sess.DB("mixdata").C("company_base").Find(where).Select(selected).Iter()
+	count := 0
+
+	typeCount := make(map[string]int)
+	for tmp := make(map[string]interface{}); query.Next(tmp); count++ {
+		if count%10000 == 0 {
+			log.Println("current:", count, tmp["company_name"], tmp["company_status"], tmp["company_type"], len(typeCount))
+		}
+
+		if util.ObjToString(tmp["company_name"]) == "" || util.ObjToString(tmp["company_type"]) == "" {
+			continue
+		}
+		company_status := util.ObjToString(tmp["company_status"])
+		if strings.Contains(company_status, "注销") || strings.Contains(company_status, "吊销") {
+			continue
+		}
+		company_type := util.ObjToString(tmp["company_type"])
+		typeCount[company_type]++
+	}
+
+	log.Println("len types", len(typeCount))
+
+	for k, v := range typeCount {
+		sa := map[string]interface{}{
+			"type":  k,
+			"count": v,
+		}
+		MgoQY.Save("wcc_company_type_static_0712", sa)
+	}
+
+	log.Println("get181Data  ---------   over ")
+}
+
+func exportByTraverseAndCount() {
+	ctx := context.Background()
+	username := ""
+	password := ""
+	//hosts := []string{"172.17.4.181:27001"}
+	hosts := []string{"172.17.4.181:27001"}
+
+	uri, err := BuildMongoURI(username, password, hosts, nil)
+	if err != nil {
+		panic(err)
+	}
+
+	clientOptions := options.Client().ApplyURI(uri)
+	client, err := mongo.Connect(ctx, clientOptions)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer client.Disconnect(ctx)
+
+	collection := client.Database("mixdata").Collection("company_base")
+
+	// 查询条件
+	filter := bson.D{
+		{"use_flag", 0},
+		{"company_status", bson.D{{"$nin", bson.A{"注销", "吊销", "吊销,已注销"}}}},
+	}
+
+	// 只查询 company_type 字段
+	opts := options.Find().SetProjection(bson.D{{"company_type", 1}})
+
+	// 创建游标
+	cursor, err := collection.Find(ctx, filter, opts)
+	if err != nil {
+		log.Fatalf("查询失败: %v", err)
+	}
+	defer cursor.Close(ctx)
+
+	// 用 map 统计
+	typeCount := make(map[string]int64)
+
+	count := 0
+	// 遍历
+	for cursor.Next(ctx) {
+		var doc struct {
+			CompanyType string `bson:"company_type"`
+		}
+		count++
+		if count%10000 == 0 {
+			log.Println("current:", count)
+		}
+		if err := cursor.Decode(&doc); err != nil {
+			log.Printf("解码失败: %v", err)
+			continue
+		}
+		if doc.CompanyType == "" {
+			continue
+		}
+		typeCount[doc.CompanyType]++
+	}
+	if err := cursor.Err(); err != nil {
+		log.Fatalf("遍历出错: %v", err)
+	}
+
+	// 写 Excel
+	f := excelize.NewFile()
+	sheet := "TypeCounts"
+	f.SetCellValue(sheet, "A1", "company_type")
+	f.SetCellValue(sheet, "B1", "count")
+
+	row := 2
+	for companyType, count := range typeCount {
+		f.SetCellValue(sheet, fmt.Sprintf("A%d", row), companyType)
+		f.SetCellValue(sheet, fmt.Sprintf("B%d", row), count)
+		row++
+	}
+
+	filename := fmt.Sprintf("company_type_counts_traverse_%d.xlsx", time.Now().Unix())
+	if err := f.SaveAs(filename); err != nil {
+		log.Fatalf("保存 Excel 失败: %v", err)
+	}
+
+	fmt.Println("\n导出完成,文件名:", filename)
+}
+
+func exportCompanyType2() {
+	ctx := context.Background()
+	username := ""
+	password := ""
+	hosts := []string{"172.17.4.181:27001"}
+
+	uri, err := BuildMongoURI(username, password, hosts, nil)
+	if err != nil {
+		panic(err)
+	}
+
+	clientOptions := options.Client().ApplyURI(uri)
+	client, err := mongo.Connect(ctx, clientOptions)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer client.Disconnect(ctx)
+
+	db := client.Database("mixdata")
+	collection := db.Collection("company_base")
+
+	// 公共 filter:use_flag=0 且 company_status != 注销 且 company_status != 吊销
+	filter := bson.M{
+		"use_flag": 0,
+		"company_status": bson.M{
+			"$nin": []string{"注销", "吊销", "吊销,已注销"},
+		},
+	}
+
+	// 第一步:distinct 不重复的 company_type
+	types, err := collection.Distinct(ctx, "company_type", filter)
+	if err != nil {
+		log.Fatalf("查询 distinct 失败: %v", err)
+	}
+	fmt.Printf("共找到 %d 个不同的 company_type\n", len(types))
+
+	// 创建 Excel 文件
+	f := excelize.NewFile()
+	sheet := "TypeCounts"
+	f.SetCellValue(sheet, "A1", "company_type")
+	f.SetCellValue(sheet, "B1", "count")
+
+	// 第二步:对每个类型 countDocuments,也带上相同 filter
+	row := 2
+	for _, t := range types {
+		strType, ok := t.(string)
+		if !ok {
+			continue
+		}
+		// 在 filter 上再加一个 company_type 条件
+		typeFilter := bson.M{
+			"use_flag": 0,
+			"company_status": bson.M{
+				"$nin": []string{"注销", "吊销", "吊销,已注销"},
+			},
+			"company_type": strType,
+		}
+
+		count, err := collection.CountDocuments(ctx, typeFilter)
+		if err != nil {
+			log.Printf("统计 %s 出错: %v", strType, err)
+			continue
+		}
+		log.Println(strType, count)
+		// 写到 Excel
+		f.SetCellValue(sheet, fmt.Sprintf("A%d", row), strType)
+		f.SetCellValue(sheet, fmt.Sprintf("B%d", row), count)
+		row++
+	}
+
+	// 保存 Excel
+	if err := f.SaveAs("company_type_counts_filtered.xlsx"); err != nil {
+		log.Fatalf("保存 Excel 失败: %v", err)
+	}
+
+	fmt.Println("导出完成,文件名:company_type_counts_filtered.xlsx")
+}
+
+func exportCompanyType() {
+	ctx := context.Background()
+	username := ""
+	password := ""
+	//hosts := []string{"127.0.0.1:27001"}
+	hosts := []string{"172.17.4.181:27001"}
+
+	uri, err := BuildMongoURI(username, password, hosts, nil)
+	if err != nil {
+		panic(err)
+	}
+
+	clientOptions := options.Client().ApplyURI(uri)
+	//clientOptions.SetDirect(true) // 如果需要 direct
+	client, err := mongo.Connect(ctx, clientOptions)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer client.Disconnect(ctx)
+
+	db := client.Database("mixdata")
+	collection := db.Collection("company_base")
+
+	// 第一步:distinct 不重复的 company_type
+	types, err := collection.Distinct(ctx, "company_type", bson.D{})
+	if err != nil {
+		log.Fatalf("查询 distinct 失败: %v", err)
+	}
+	fmt.Printf("共找到 %d 个不同的 company_type\n", len(types))
+
+	// 创建 Excel 文件
+	f := excelize.NewFile()
+	sheet := "TypeCounts"
+	f.SetCellValue(sheet, "A1", "company_type")
+	f.SetCellValue(sheet, "B1", "count")
+
+	// 第二步:对每个类型 countDocuments
+	row := 2
+	for _, t := range types {
+		strType, ok := t.(string)
+		if !ok {
+			continue
+		}
+		count, err := collection.CountDocuments(ctx, bson.M{"company_type": strType})
+		if err != nil {
+			log.Printf("统计 %s 出错: %v", strType, err)
+			continue
+		}
+		log.Println(strType, count)
+		// 写到 Excel
+		f.SetCellValue(sheet, fmt.Sprintf("A%d", row), strType)
+		f.SetCellValue(sheet, fmt.Sprintf("B%d", row), count)
+		row++
+	}
+
+	// 保存 Excel
+	if err := f.SaveAs("company_type_counts_fast.xlsx"); err != nil {
+		log.Fatalf("保存 Excel 失败: %v", err)
+	}
+
+	fmt.Println("导出完成,文件名:company_type_counts_fast.xlsx")
+}
+
 type Enterprise struct {
 	CompanyName string  `bson:"company_name"`
 	CompanyType string  `bson:"company_type"`
@@ -44,6 +333,7 @@ func matchSpecialEnterprise() {
 	if err != nil {
 		panic(err)
 	}
+
 	// MongoDB连接
 	client, err := mongo.Connect(ctx, options.Client().ApplyURI(uri))
 	if err != nil {

+ 543 - 0
xlsx/company_type.go

@@ -0,0 +1,543 @@
+package main
+
+import (
+	"fmt"
+	"github.com/xuri/excelize/v2"
+	"log"
+	"regexp"
+	"strings"
+)
+
+// 循环外:私营企业code集合
+var privateCodes = map[string]bool{
+	"1130": true, "1151": true, "1152": true, "1212": true, "1222": true,
+	"2130": true, "2151": true, "2152": true, "2212": true, "2222": true,
+	"4531": true, "4532": true, "4533": true, "4540": true, "4551": true,
+	"4552": true, "4553": true, "4560": true,
+}
+
+// dealZhuTi 处理经营主体
+func dealZhuTi() {
+	// 打开 Excel
+	filePath := "经营主体类型.xlsx" // TODO: 改成真实的 xlsx 文件路径
+	f, err := excelize.OpenFile(filePath)
+	if err != nil {
+		log.Fatalf("打开文件失败: %v", err)
+	}
+
+	// 假设只有一个 sheet
+	sheetName := f.GetSheetName(0)
+	// 先构造代码 -> 名称 map
+	codeNameMap := make(map[string]string)
+
+	rows, err := f.GetRows(sheetName)
+	if err != nil {
+		log.Fatalf("读取行失败: %v", err)
+	}
+
+	for idx, row := range rows {
+		// 跳过表头
+		if idx == 0 {
+			continue
+		}
+		if len(row) < 2 {
+			continue
+		}
+		code := strings.TrimSpace(row[0])
+		name := strings.TrimSpace(row[1])
+		// 替换中文括号为英文括号
+		name = strings.ReplaceAll(name, "(", "(")
+		name = strings.ReplaceAll(name, ")", ")")
+		codeNameMap[code] = name
+	}
+
+	// 遍历数据行,新增四列
+	for idx, row := range rows {
+		if idx == 0 {
+			// 表头
+			_ = f.SetCellValue(sheetName, fmt.Sprintf("D%d", idx+1), "第一位名称")
+			_ = f.SetCellValue(sheetName, fmt.Sprintf("E%d", idx+1), "第二位名称")
+			_ = f.SetCellValue(sheetName, fmt.Sprintf("F%d", idx+1), "第三位名称")
+			_ = f.SetCellValue(sheetName, fmt.Sprintf("G%d", idx+1), "第四位名称")
+			_ = f.SetCellValue(sheetName, fmt.Sprintf("H%d", idx+1), "层级")
+			_ = f.SetCellValue(sheetName, fmt.Sprintf("I%d", idx+1), "标签1")
+			continue
+		}
+		if len(row) < 2 {
+			continue
+		}
+		code := strings.TrimSpace(row[0])
+		name := strings.TrimSpace(row[1])
+		name = strings.ReplaceAll(name, "(", "(")
+		name = strings.ReplaceAll(name, ")", ")")
+
+		// 判断标签
+		tag := "内资企业"
+		if strings.HasPrefix(code, "5") || strings.HasPrefix(code, "7") || code == "8500" {
+			tag = "外企"
+		} else if strings.HasPrefix(code, "6") {
+			tag = "外企-港澳台"
+		} else if strings.HasPrefix(code, "91") || strings.HasPrefix(code, "92") {
+			tag = "农合"
+		} else if strings.HasPrefix(code, "95") {
+			tag = "个体工商户"
+		} else if privateCodes[code] {
+			tag = "私营企业"
+		}
+
+		if len(code) != 4 {
+			continue
+		}
+
+		// 层级判断
+		level := 4
+		if strings.HasSuffix(code, "000") {
+			level = 1
+		} else if strings.HasSuffix(code, "00") {
+			level = 2
+		} else if strings.HasSuffix(code, "0") {
+			level = 3
+		}
+
+		// 各层级代码
+		firstCode := code[:1] + "000"
+		secondCode := code[:2] + "00"
+		thirdCode := code[:3] + "0"
+		fourthCode := code
+
+		firstName := ""
+		secondName := ""
+		thirdName := ""
+		fourthName := ""
+
+		// 根据层级决定填哪些
+		if level >= 1 {
+			firstName = codeNameMap[firstCode]
+		}
+		if level >= 2 {
+			secondName = codeNameMap[secondCode]
+		}
+		if level >= 3 {
+			thirdName = codeNameMap[thirdCode]
+		}
+		if level == 4 {
+			fourthName = codeNameMap[fourthCode]
+		}
+
+		// B列加缩进
+		indent := strings.Repeat("  ", level-1) // 每层两个空格
+		newName := indent + name
+		rowNum := idx + 1
+		// 写回新的名称到 B 列
+		_ = f.SetCellValue(sheetName, fmt.Sprintf("B%d", rowNum), newName)
+
+		// 写层级名称列
+		_ = f.SetCellValue(sheetName, fmt.Sprintf("D%d", rowNum), firstName)
+		_ = f.SetCellValue(sheetName, fmt.Sprintf("E%d", rowNum), secondName)
+		_ = f.SetCellValue(sheetName, fmt.Sprintf("F%d", rowNum), thirdName)
+		_ = f.SetCellValue(sheetName, fmt.Sprintf("G%d", rowNum), fourthName)
+		_ = f.SetCellValue(sheetName, fmt.Sprintf("H%d", rowNum), level)
+		_ = f.SetCellValue(sheetName, fmt.Sprintf("I%d", rowNum), tag)
+
+	}
+
+	// 保存新文件
+	err = f.SaveAs("经营主体类型-result3.xlsx")
+	if err != nil {
+		log.Fatalf("保存文件失败: %v", err)
+	}
+	fmt.Println("处理完成,结果保存在 经营主体类型-result3.xlsx")
+}
+
+// matchCompanyType 根据企业类型,返回标准经营主体代码
+func matchCompanyType() {
+	// ⚙️ Excel 文件名
+	inputFile := "company_types.xlsx"
+	outputFile := "company_types_out.xlsx"
+
+	// 📂 打开 Excel 文件
+	f, err := excelize.OpenFile(inputFile)
+	if err != nil {
+		log.Fatalf("无法打开文件: %v", err)
+	}
+	defer f.Close()
+
+	// ✅ 加载经营主体类型 Sheet
+	codeMap, err := loadCodeMap(f, "经营主体类型")
+	nameMap, err := loadNameMap(f, "经营主体类型")
+	if err != nil {
+		log.Fatalf("加载经营主体类型失败: %v", err)
+	}
+
+	// 🔍 正则,用于提取4位数字
+	re4 := regexp.MustCompile(`\d{4}`)
+
+	// 📄 遍历 Sheet2
+	sheetName := "Sheet2"
+	rows, err := f.GetRows(sheetName)
+	if err != nil {
+		log.Fatalf("读取 Sheet2 失败: %v", err)
+	}
+
+	for idx, row := range rows {
+		if len(row) == 0 {
+			continue
+		}
+		originText := strings.TrimSpace(row[0])
+		if originText == "" {
+			continue
+		}
+
+		var code string
+		// 去除引号
+		cleanText := strings.ReplaceAll(originText, `"`, "")
+		cleanText = strings.TrimSpace(cleanText)
+		// 替换中文括号为英文括号
+		cleanText = strings.ReplaceAll(cleanText, "(", "(")
+		cleanText = strings.ReplaceAll(cleanText, ")", ")")
+		cleanText = strings.ReplaceAll(cleanText, "外资比例低于25%", "")
+
+		// 判断是不是日期(如 2008/10/31)
+		if matched, _ := regexp.MatchString(`^\d{4}/\d{1,2}/\d{1,2}$`, cleanText); matched {
+			log.Printf("跳过日期行: %s", cleanText)
+			continue
+		}
+		// 如果包含“年”/“月”/“日”等,也跳过(不提取数字)
+		if strings.Contains(cleanText, "年") || strings.Contains(cleanText, "月") || strings.Contains(cleanText, "日") {
+			log.Printf("跳过含日期描述的行: %s", cleanText)
+			continue
+		}
+
+		// 优先提取4位数字
+		if m := re4.FindString(cleanText); m != "" {
+			code = m
+		} else {
+			// 去除引号后完全匹配
+			if c, ok := codeMap[cleanText]; ok {
+				code = c
+			}
+		}
+
+		//匹配不到时,需要 提取信息;然后重新匹配
+		code = getCodeByCompanyType(cleanText, codeMap)
+
+		// ✏️ 如果匹配到,就写到 B 列
+		if code != "" {
+			cell, _ := excelize.CoordinatesToCellName(2, idx+1)  // B列
+			cell2, _ := excelize.CoordinatesToCellName(3, idx+1) // B列
+			if err := f.SetCellValue(sheetName, cell, code); err != nil {
+				log.Printf("写入单元格失败 %s: %v", cell, err)
+			}
+
+			if err = f.SetCellValue(sheetName, cell2, nameMap[code]); err != nil {
+				log.Printf("写入单元格失败 %s: %v", cell2, err)
+			}
+		} else {
+			log.Printf("未匹配: %s", originText)
+		}
+	}
+
+	// 💾 保存结果
+	if err := f.SaveAs(outputFile); err != nil {
+		log.Fatalf("保存文件失败: %v", err)
+	}
+
+	fmt.Printf("✅ 处理完成!输出文件:%s\n", outputFile)
+}
+
+// getCodeByCompanyType  根据企业类型,返回经营主体代码
+func getCodeByCompanyType(cleanText string, codeMap map[string]string) (code string) {
+	if code == "" {
+		//一人有限责任公司
+		if strings.Contains(cleanText, "一人有限责任公司分公司") {
+			cleanText = "一人有限责任公司分公司"
+		} else if strings.Contains(cleanText, "一人有限责任公司") {
+			cleanText = "一人有限责任公司"
+		} else if cleanText == "有限责任(公司)" {
+			cleanText = "有限责任公司"
+		} else if cleanText == "上市股份有限公司分公司" {
+			cleanText = "股份有限公司分公司(上市)"
+		} else if cleanText == "上市股份有限公司分公司(非上市)" {
+			cleanText = "股份有限公司分公司(非上市)"
+		} else if !strings.Contains(cleanText, "非个人") && !strings.Contains(cleanText, "非个体") {
+			if strings.Contains(cleanText, "个人") || strings.Contains(cleanText, "个体") || strings.Contains(cleanText, "户体商工个") {
+				cleanText = "个体工商户"
+			}
+		} else if strings.Contains(cleanText, "中外合作") { // 中外合作企业 - 有限责任公司(中外合作)
+			if strings.Contains(cleanText, "非公司外商投资企业(中外合作)") {
+				cleanText = "非公司外商投资企业(中外合作)"
+			} else {
+				cleanText = "有限责任公司(中外合作)"
+			}
+		} else if strings.Contains(cleanText, "有限责任公司(中外合资)") { //有限责任公司(中外合资)
+			cleanText = "有限责任公司(中外合资)"
+		} else if strings.Contains(cleanText, "外商投资企业分支机构") { //非公司外商投资企业分支机构;外商投资企业分支机构
+			if strings.Contains(cleanText, "非公司") {
+				cleanText = "非公司外商投资企业分支机构"
+			} else {
+				cleanText = "外商投资企业分支机构"
+			}
+		} else if strings.Contains(cleanText, "其他") {
+			//有限责任公司(港、澳、台)
+			if strings.Contains(cleanText, "港、澳、台") {
+				if strings.Contains(cleanText, "有限责任公司") {
+					cleanText = "有限责任公司(港、澳、台)"
+				} else if strings.Contains(cleanText, "非公司") {
+					code = "6300"
+					cleanText = "非公司"
+				}
+			}
+		} else if strings.Contains(cleanText, "有限责任公司(台港澳与境内合作)") {
+			cleanText = "有限责任公司(台港澳与境内合作)"
+		} else if strings.Contains(cleanText, "有限责任公司(台港澳与境内合资)") {
+			cleanText = "有限责任公司(台港澳与境内合资)"
+		} else if strings.Contains(cleanText, "有限责任公司(台港澳与外国投资者合资)") {
+			cleanText = "有限责任公司(台港澳与外国投资者合资)"
+		} else if strings.Contains(cleanText, "有限责任公司(台港澳合资)") || (strings.Contains(cleanText, "台、港、澳资") && strings.Contains(cleanText, "有限责任公司")) {
+			cleanText = "有限责任公司(台港澳合资)"
+		} else if strings.Contains(cleanText, "有限责任公司(台港澳法人独资)") {
+			cleanText = "有限责任公司(港澳台法人独资)"
+		} else if strings.Contains(cleanText, "有限责任公司(台港澳自然人独资)") {
+			cleanText = "有限责任公司(港澳台自然人独资)"
+		} else if strings.Contains(cleanText, "有限责任公司(外商合资)") {
+			cleanText = "有限责任公司(外商合资)"
+		} else if strings.Contains(cleanText, "有限责任公司(外商投资") {
+			cleanText = "有限责任公司(外商投资、非独资)"
+		} else if strings.Contains(cleanText, "有限责任公司(外国法人独资)") {
+			cleanText = "有限责任公司(外国法人独资)"
+		} else if strings.Contains(cleanText, "外国非法人经济组织独资") {
+			cleanText = "外国非法人经济组织独资"
+		} else if strings.Contains(cleanText, "有限责任公司(外国自然人独资)") || strings.Contains(cleanText, "有限责任公司(外自然人独资)") {
+			cleanText = "有限责任公司(外国自然人独资)"
+		} else if strings.Contains(cleanText, "有限责任公司(法人独资)(外商投资企业投资)") {
+			cleanText = "有限责任公司分公司(外商投资企业法人独资)"
+		} else if strings.Contains(cleanText, "有限责任公司(港、澳、台)") || strings.Contains(cleanText, "有限责任公司(港澳台合资)") {
+			cleanText = "有限责任公司(台港澳合资)"
+		} else if strings.Contains(cleanText, "有限责任公司") || strings.Contains(cleanText, "港澳台与境内合作") {
+			cleanText = "有限责任公司(台港澳与境内合作)"
+		} else if strings.Contains(cleanText, "港澳台与境内合资") && strings.Contains(cleanText, "有限责任公司") {
+			cleanText = "有限责任公司(台港澳与境内合资)"
+		} else
+		// 这个需要和贾老师确认
+		if strings.Contains(cleanText, "有限责任公司(法人独资") && strings.Contains(cleanText, "私营") {
+			cleanText = "有限责任公司(非自然人投资或控股的法人独资)"
+		} else if strings.Contains(cleanText, "港澳台与外国投资者合资") && strings.Contains(cleanText, "有限责任公司") {
+			cleanText = "有限责任公司(台港澳与外国投资者合资)"
+		} else if strings.Contains(cleanText, "港澳台法人独资") && strings.Contains(cleanText, "有限责任公司") {
+			cleanText = "有限责任公司(港澳台法人独资)"
+		} else if strings.Contains(cleanText, "港澳台自然人独资") && strings.Contains(cleanText, "有限责任公司") {
+			cleanText = "有限责任公司(港澳台自然人独资)"
+		} else if strings.Contains(cleanText, "有限责任公司(港澳台非法人经济组织独资)") {
+			cleanText = "有限责任公司(台港澳非法人经济组织独资)"
+		} else if strings.Contains(cleanText, "港澳台投资、非独资") && strings.Contains(cleanText, "有限责任公司") {
+			cleanText = "有限责任公司(港澳台投资、非独资)"
+		} else if strings.Contains(cleanText, "港澳台合资") && strings.Contains(cleanText, "未上市") {
+			if strings.Contains(cleanText, "股份有限公司") {
+				code = "6230"
+			}
+		} else if strings.Contains(cleanText, "集体所有制") {
+			cleanText = "集体所有制"
+		} else if strings.Contains(cleanText, "国有独资") {
+			if strings.Contains(cleanText, "有限责公司分公司") {
+				cleanText = "有限责任公司分公司(国有独资)"
+			} else if strings.Contains(cleanText, "有限责公司") {
+				cleanText = "有限责任公司(国有独资)"
+			}
+		} else
+		//台、港、澳
+		if strings.Contains(cleanText, "台、港、澳") {
+			if strings.Contains(cleanText, "台、港、澳分公司") || strings.Contains(cleanText, "台、港、澳投资企业分公司") || strings.Contains(cleanText, "台、港、澳投资公司分公司") {
+				code = "6810"
+			}
+			if strings.Contains(cleanText, "台、港、澳办事处") {
+				code = "6830"
+			}
+			if strings.Contains(cleanText, "台、港、澳投资企业") {
+				code = "6000"
+			}
+			if strings.Contains(cleanText, "台、港、澳投资企业其他") {
+				code = "6190"
+			}
+		} else if cleanText == "股份有限公司分支机构(台港澳与境内合资)" {
+			code = "6220"
+		} else if strings.Contains(cleanText, "台港澳投资企业办事处") {
+			code = "6830"
+		} else if strings.Contains(cleanText, "台港澳投资有限合伙企业") {
+			code = "6400"
+		} else if strings.Contains(cleanText, "台港澳投资普通合伙企业分支机构") {
+			code = "6840"
+		} else if strings.Contains(cleanText, "台港澳投资特殊普通合伙企业分支机构") {
+			code = "6420"
+		} else if strings.Contains(cleanText, "台港澳股份有限公司") {
+			code = "6200"
+		} else if strings.Contains(cleanText, "台港澳非公司") {
+			code = "6300"
+		} else if cleanText == "国外投资" {
+			code = "5000"
+		} else if strings.Contains(cleanText, "国有事业单位营业") {
+			cleanText = "国有事业单位营业"
+		} else if strings.Contains(cleanText, "国有控股") {
+			if strings.Contains(cleanText, "非上市") {
+				if strings.Contains(cleanText, "股份有限公司分公司") {
+					code = "1223"
+				}
+			} else if strings.Contains(cleanText, "上市") {
+				if strings.Contains(cleanText, "股份有限公司分公司") {
+					code = "2213"
+					cleanText = "股份有限公司分公司(上市、国有控股)"
+				}
+			} else if strings.Contains(cleanText, "股份有限公司分公司") {
+				code = "2223"
+			} else if strings.Contains(cleanText, "有限责任公司分公司") {
+				code = "2140"
+			} else if strings.Contains(cleanText, "有限责任公司") {
+				code = "1140"
+			}
+		} else if strings.Contains(cleanText, "国有") {
+			if strings.Contains(cleanText, "经营单位") && strings.Contains(cleanText, "非法人") {
+				code = "4410"
+				cleanText = "国有经营单位(非法人)"
+			} else if strings.Contains(cleanText, "国有联营") {
+				code = "4600"
+			}
+		} else
+		//合伙企业
+		if strings.Contains(cleanText, "合伙企业") {
+			if strings.Contains(cleanText, "特殊普通合伙") {
+				code = "4532"
+			} else if strings.Contains(cleanText, "普通合伙") {
+				code = "4530"
+			} else if strings.Contains(cleanText, "有限合伙") {
+				code = "4533"
+			} else if strings.Contains(cleanText, "合伙企业分支机构") {
+				code = "4550"
+			}
+		} else if strings.Contains(cleanText, "合伙私营企业") {
+			code = "4530"
+		} else if cleanText == "内资企业法人联营" {
+			cleanText = "联营"
+		} else
+		//农民专业合作社分支机构
+		if strings.Contains(cleanText, "合作社") {
+			if strings.Contains(cleanText, "农民专业合作社分支机构") {
+				cleanText = "农民专业合作社分支机构"
+			} else if strings.Contains(cleanText, "农民专业合作社") {
+				cleanText = "农民专业合作社"
+			} else if strings.Contains(cleanText, "合作社分支机构") {
+				cleanText = "农民专业合作社分支机构"
+			} else {
+				cleanText = "农民专业合作社"
+			}
+		} else if strings.Contains(cleanText, "非公司") {
+			if strings.Contains(cleanText, "港、澳、台投资企业分支机构") {
+				cleanText = "非公司台、港、澳投资企业分支机构"
+				code = "6820"
+			} else if strings.Contains(cleanText, "港、澳、台企业(港澳台合资)") {
+				cleanText = "非公司台、港、澳企业(台港澳与境内合作)"
+				code = "6310"
+			} else if strings.Contains(cleanText, "非公司外商投资企业") && strings.Contains(cleanText, "其他") {
+				code = "5390"
+			}
+		} else if strings.Contains(cleanText, "股份有限公司(上市公司)") {
+			cleanText = "股份有限公司(上市)"
+			code = "1210"
+		} else if strings.Contains(cleanText, "股份有限公司(中外合资、上市)") {
+			cleanText = "股份有限公司(中外合资、上市)"
+			code = "5220"
+		} else if strings.Contains(cleanText, "股份有限公司(中外合资、未上市)") || strings.Contains(cleanText, "股份有限公司(中外合资,未上市)") {
+			cleanText = "股份有限公司(中外合资、未上市)"
+			code = "5210"
+		} else if cleanText == "股份有限公司(其他)" {
+			code = "5290"
+		} else if strings.Contains(cleanText, "股份有限公司(其他台港澳股份有限公司)") {
+			code = "6290"
+		} else if cleanText == "股份有限公司(台、港、澳资)" {
+			code = "6270"
+		} else if strings.Contains(cleanText, "股份有限公司(台港澳与境内合资、上市)") || strings.Contains(cleanText, "股份有限公司(台港澳与境内合资,上市)") {
+			cleanText = "股份有限公司(台港澳与境内合资、上市)"
+			code = "6220"
+		} else if strings.Contains(cleanText, "股份有限公司(台港澳与境内合资、未上市)") {
+			cleanText = "股份有限公司(台港澳与境内合资、未上市)"
+			code = "6210"
+		} else if strings.Contains(cleanText, "股份有限公司(台港澳与外国投资者合资、未上市)") {
+			cleanText = "股份有限公司(台港澳与外国投资者合资、未上市)"
+			code = "6250"
+		} else if strings.Contains(cleanText, "股份有限公司(台港澳合资、上市)") {
+			cleanText = "股份有限公司(台港澳合资、上市)"
+			code = "6240"
+		} else if strings.Contains(cleanText, "股份有限公司(台港澳合资、未上市)") {
+			cleanText = "股份有限公司(台港澳合资、未上市)"
+			code = "6230"
+		} else if cleanText == "股份有限公司(港、澳、台)" {
+			code = "6200"
+		} else {
+
+		}
+		// 判断是不是日期(如 2008/10/31)
+		if matched, _ := regexp.MatchString(`^\d{4}/\d{1,2}/\d{1,2}$`, cleanText); matched {
+			log.Printf("跳过日期行: %s", cleanText)
+			return
+		}
+		// 如果包含“年”/“月”/“日”等,也跳过(不提取数字)
+		if strings.Contains(cleanText, "年") || strings.Contains(cleanText, "月") || strings.Contains(cleanText, "日") {
+			log.Printf("跳过含日期描述的行: %s", cleanText)
+			return
+		}
+
+		cleanText = strings.TrimSpace(cleanText)
+		cleanText = strings.ReplaceAll(cleanText, "(", "(")
+		cleanText = strings.ReplaceAll(cleanText, ")", ")")
+		if code == "" {
+			if c, ok := codeMap[cleanText]; ok {
+				code = c
+			}
+		}
+	}
+
+	return code
+}
+
+// 📦 加载经营主体类型 Sheet,返回 名称=>代码 的映射
+func loadCodeMap(f *excelize.File, sheetName string) (map[string]string, error) {
+	codeMap := make(map[string]string)
+	rows, err := f.GetRows(sheetName)
+	if err != nil {
+		return nil, err
+	}
+	for idx, row := range rows {
+		if idx == 0 {
+			continue // 跳过表头
+		}
+		if len(row) >= 2 {
+			name := strings.TrimSpace(row[1])
+			code := strings.TrimSpace(row[0])
+			// 替换中文括号为英文括号
+			name = strings.ReplaceAll(name, "(", "(")
+			name = strings.ReplaceAll(name, ")", ")")
+			codeMap[name] = code
+		}
+	}
+	return codeMap, nil
+}
+
+func loadNameMap(f *excelize.File, sheetName string) (map[string]string, error) {
+	codeMap := make(map[string]string)
+	rows, err := f.GetRows(sheetName)
+	if err != nil {
+		return nil, err
+	}
+	for idx, row := range rows {
+		if idx == 0 {
+			continue // 跳过表头
+		}
+		if len(row) >= 2 {
+			name := strings.TrimSpace(row[1])
+			code := strings.TrimSpace(row[0])
+			// 替换中文括号为英文括号
+			name = strings.ReplaceAll(name, "(", "(")
+			name = strings.ReplaceAll(name, ")", ")")
+			codeMap[code] = name
+		}
+	}
+	return codeMap, nil
+}

BIN
xlsx/company_types.xlsx


+ 8 - 2
xlsx/go.mod

@@ -1,6 +1,8 @@
 module xlsx
 
-go 1.20
+go 1.22
+
+toolchain go1.23.7
 
 require (
 	github.com/olivere/elastic/v7 v7.0.32
@@ -31,6 +33,7 @@ require (
 	github.com/josharian/intern v1.0.0 // indirect
 	github.com/klauspost/compress v1.16.7 // indirect
 	github.com/mailru/easyjson v0.7.7 // indirect
+	github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
 	github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
 	github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
 	github.com/paulmach/orb v0.10.0 // indirect
@@ -38,7 +41,9 @@ require (
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/richardlehane/mscfb v1.0.4 // indirect
 	github.com/richardlehane/msoleps v1.0.3 // indirect
+	github.com/rivo/uniseg v0.4.7 // indirect
 	github.com/robfig/cron/v3 v3.0.1 // indirect
+	github.com/schollz/progressbar/v3 v3.18.0 // indirect
 	github.com/segmentio/asm v1.2.0 // indirect
 	github.com/shopspring/decimal v1.3.1 // indirect
 	github.com/xdg-go/pbkdf2 v1.0.0 // indirect
@@ -52,7 +57,8 @@ require (
 	golang.org/x/crypto v0.14.0 // indirect
 	golang.org/x/net v0.17.0 // indirect
 	golang.org/x/sync v0.3.0 // indirect
-	golang.org/x/sys v0.13.0 // indirect
+	golang.org/x/sys v0.29.0 // indirect
+	golang.org/x/term v0.28.0 // indirect
 	golang.org/x/text v0.13.0 // indirect
 	gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect

+ 10 - 0
xlsx/go.sum

@@ -1418,6 +1418,8 @@ github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy
 github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
 github.com/mistifyio/go-zfs/v3 v3.0.1/go.mod h1:CzVgeB0RvF2EGzQnytKVvVSDwmKJXxkOTUGbNrTja/k=
 github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
+github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
+github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
 github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
@@ -1636,6 +1638,8 @@ github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7
 github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
 github.com/richardlehane/msoleps v1.0.3 h1:aznSZzrwYRl3rLKRT3gUk9am7T/mLNSnJINvN0AQoVM=
 github.com/richardlehane/msoleps v1.0.3/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
+github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
+github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
 github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
 github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
 github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
@@ -1657,6 +1661,8 @@ github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiB
 github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
 github.com/safchain/ethtool v0.2.0/go.mod h1:WkKB1DnNtvsMlDmQ50sgwowDJV/hGbJSOvJoEXs1AJQ=
 github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
+github.com/schollz/progressbar/v3 v3.18.0 h1:uXdoHABRFmNIjUfte/Ex7WtuyVslrw2wVPQmCN62HpA=
+github.com/schollz/progressbar/v3 v3.18.0/go.mod h1:IsO3lpbaGuzh8zIMzgY3+J8l4C8GjO0Y9S69eFvNsec=
 github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
 github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
@@ -2322,6 +2328,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
 golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
+golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@@ -2338,6 +2346,8 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
 golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
 golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
 golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
+golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
+golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

+ 83 - 0
xlsx/govement.go

@@ -0,0 +1,83 @@
+package main
+
+import (
+	"fmt"
+	"github.com/xuri/excelize/v2"
+	"log"
+	"strings"
+)
+
+// matGovSite 匹配政府网站站点情况
+func matGovSite() {
+	// 文件路径
+	listFile := "政府网站清单.xlsx"
+	treeFile := "中国政府机构目录树0425.xlsx"
+
+	// 打开政府网站清单.xlsx
+	listF, err := excelize.OpenFile(listFile)
+	if err != nil {
+		log.Fatalf("无法打开文件 %s: %v", listFile, err)
+	}
+	defer listF.Close()
+
+	// 打开目录树文件
+	treeF, err := excelize.OpenFile(treeFile)
+	if err != nil {
+		log.Fatalf("无法打开文件 %s: %v", treeFile, err)
+	}
+	defer treeF.Close()
+
+	// 获取政府网站清单.xlsx Sheet1 中 D 列的所有值
+	listRows, err := listF.GetRows("Sheet1")
+	if err != nil {
+		log.Fatalf("读取 Sheet1 出错: %v", err)
+	}
+
+	// 保存到 map 中,提高匹配速度
+	matchingSet := make(map[string]struct{})
+	for idx, row := range listRows {
+		// Excel 列是从 0 开始的,D列是 index=3
+		if len(row) > 3 {
+			value := strings.TrimSpace(row[3])
+			if value != "" {
+				matchingSet[value] = struct{}{}
+			}
+		} else {
+			fmt.Println(22222)
+		}
+		// 如果非常大数据,可以做分批或加提示
+		if idx%5000 == 0 {
+			fmt.Printf("已读取 %d 条数据\n", idx)
+		}
+	}
+	fmt.Printf("共收集待匹配关键字:%d 条\n", len(matchingSet))
+
+	// 打开目录树 Sheet
+	treeSheet := "组织架构带层级"
+	treeRows, err := treeF.GetRows(treeSheet)
+	if err != nil {
+		log.Fatalf("读取 %s 出错: %v", treeSheet, err)
+	}
+
+	// 遍历目录树的 D 列,匹配
+	for i, row := range treeRows {
+		if len(row) > 3 {
+			orgName := strings.TrimSpace(row[3])
+			if _, ok := matchingSet[orgName]; ok {
+				// i 从 0 开始,对应 Excel 第 i+1 行,I 列是第9列,对应字母 "I"
+				cell := fmt.Sprintf("I%d", i+1)
+				err := treeF.SetCellValue(treeSheet, cell, "是")
+				if err != nil {
+					log.Printf("写入单元格 %s 出错: %v", cell, err)
+				}
+			}
+		}
+	}
+
+	// 保存新文件
+	outputFile := "中国政府机构目录树0425_已标记.xlsx"
+	if err := treeF.SaveAs(outputFile); err != nil {
+		log.Fatalf("保存新文件出错: %v", err)
+	}
+	fmt.Println("处理完成,已生成文件:", outputFile)
+}

+ 5 - 0
xlsx/main.go

@@ -30,6 +30,11 @@ type WinnerData struct {
 }
 
 func main() {
+
+	//matGovSite()
+	//get181Data()
+	log.Println("11111111")
+	return
 	//导出数据到Excel
 	//exportBidding()
 

+ 68 - 0
xlsx/xlsx_test.go

@@ -6,6 +6,9 @@ import (
 	"fmt"
 	"github.com/olivere/elastic/v7"
 	"github.com/xuri/excelize/v2"
+	"go.mongodb.org/mongo-driver/bson"
+	"go.mongodb.org/mongo-driver/mongo"
+	"go.mongodb.org/mongo-driver/mongo/options"
 	util "jygit.jydev.jianyu360.cn/data_processing/common_utils"
 	"jygit.jydev.jianyu360.cn/data_processing/common_utils/mongodb"
 	"log"
@@ -16,6 +19,71 @@ import (
 	"time"
 )
 
+func TestExportCompanyType(T *testing.T) {
+	ctx := context.Background()
+	// MongoDB 连接字符串
+	username := ""
+	password := ""
+	//hosts := []string{"172.17.4.181:27001"}
+	hosts := []string{"127.0.0.1:27001"}
+
+	uri, err := BuildMongoURI(username, password, hosts, nil)
+	if err != nil {
+		panic(err)
+	}
+
+	// MongoDB连接
+	clientOptions := options.Client().ApplyURI(uri)
+	clientOptions.SetDirect(true)
+	client, err := mongo.Connect(ctx, clientOptions)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer client.Disconnect(ctx)
+
+	db := client.Database("mixdata")
+	collection := db.Collection("company_base")
+
+	filter := bson.M{
+		"company_status": bson.M{"$nin": []string{"注销", "吊销", "已吊销", "已注销"}},
+		"use_flag":       0,
+	}
+	// 查询 distinct company_type
+	types, err := collection.Distinct(ctx, "company_type", filter)
+	if err != nil {
+		log.Fatalf("查询 distinct 失败: %v", err)
+	}
+
+	fmt.Printf("共找到 %d 个 company_type\n", len(types))
+
+	// 创建 Excel 文件
+	f := excelize.NewFile()
+	sheet := "Sheet1"
+
+	// 设置第一行标题
+	f.SetCellValue(sheet, "A1", "company_type")
+
+	// 填写数据
+	for i, t := range types {
+		// 强制转成字符串
+		str, ok := t.(string)
+		if !ok {
+			// 如果不是字符串,跳过
+			continue
+		}
+		// Excel 行号从 2 开始
+		cell := fmt.Sprintf("A%d", i+2)
+		f.SetCellValue(sheet, cell, str)
+	}
+
+	// 保存 Excel 文件
+	if err := f.SaveAs("company_types.xlsx"); err != nil {
+		log.Fatalf("保存 Excel 失败: %v", err)
+	}
+
+	fmt.Println("导出完成,文件名:company_types0711.xlsx")
+}
+
 func TestA(T *testing.T) {
 	Mgo := &mongodb.MongodbSim{
 		//MongodbAddr: "172.17.189.140:27080",

BIN
xlsx/中国政府机构目录树0425.xlsx


BIN
xlsx/中国政府机构目录树0425_已标记.xlsx


BIN
xlsx/政府网站清单.xlsx


BIN
xlsx/经营主体类型-result.xlsx


BIN
xlsx/经营主体类型-result2.xlsx


BIN
xlsx/经营主体类型-result3.xlsx


BIN
xlsx/经营主体类型.xlsx