刘光辉
13 小时以前 34981c30a78e8bbd7791131059a9210f9928b62c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
package jnpf.base.model.ocr.model;
 
import com.alibaba.fastjson.JSONObject;
import io.swagger.v3.oas.annotations.media.Schema;
import jnpf.base.model.ocr.OcrModel;
import jnpf.util.DateUtil;
import jnpf.util.StringUtil;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
 
import java.util.*;
import java.util.regex.Pattern;
 
/**
 * ocr解析营业执照模型
 *
 * @author JNPF开发平台组
 * @version v6.1.0
 * @copyright 引迈信息技术有限公司
 * @date 2025/7/29 16:58:47
 */
@EqualsAndHashCode(callSuper = true)
@Data
@Schema(description = "ocr解析营业执照模型")
@NoArgsConstructor
public class BusinessLicModel extends OcrModel {
    @Schema(description = TYSHXYDM)
    private String code;
    @Schema(description = "企业名称")
    private String name;
    @Schema(description = "企业类型")
    private String businessType;
    @Schema(description = "法定代表人")
    private String userName;
    @Schema(description = "经营范围")
    private String businessScope;
    @Schema(description = "注册资本")
    private String capital;
    @Schema(description = "成立日期")
    private Long createDate;
    @Schema(description = "营业期限")
    private String timeLimit;
    @Schema(description = "地址")
    private String address;
 
    private static final String TYSHXYDM = "统一社会信用代码";
 
    @Override
    public void extract(String url, JSONObject body) {
        super.extract(url, body);
        if (StringUtil.isEmpty(this.getContent()) || !this.getContent().contains("营业执照")) {
            return;
        }
        this.setOther();
        validateCode();
        businessScope();
        this.setContent(null);
        this.setStrList(null);
    }
 
    /**
     * 统一社会信用代码识别补充
     */
    public void validateCode() {
        Pattern pattern = Pattern.compile("^[0-9A-HJ-NPQRTUWXY]{2}\\d{6}[0-9A-HJ-NPQRTUWXY]{10}$");
        if (StringUtil.isEmpty(code) || code.trim().length() != 18 || pattern.matcher(code).matches()) {
            int index = this.getContent().indexOf(TYSHXYDM) + 8;
            String str = this.getContent().substring(index, index + 18);
            // 先进行正则表达式验证
            if (pattern.matcher(str).matches()) {
                this.code = str;
            } else {
                for (String item : this.getStrList()) {
                    if (pattern.matcher(item).matches()) {
                        this.code = item;
                        return;
                    }
                }
            }
        }
    }
 
    /**
     * 经营范围和住所识别补充
     */
    public void businessScope() {
        int codeIndex = this.getContent().indexOf("经营范围");
        int addressIndex = this.getContent().indexOf("住所");
        if (codeIndex > 0 && addressIndex > 0 && codeIndex < addressIndex) {
            int start = 0;
            int end = 0;
            int size = this.getStrList().size();
            int addressStart = 0;
            int addressEnd = 0;
            for (int i = 0; i < size; i++) {
                if (this.getStrList().get(i).startsWith("经营范围")) {
                    start = i;
                }
                if (this.getStrList().get(i).startsWith("住")) {
                    addressStart = i;
                }
                if (this.getStrList().get(i).startsWith("所")) {
                    addressEnd = i;
                }
                if (this.getStrList().get(i).startsWith("登记机关")) {
                    end = i;
                    break;
                }
            }
            if (addressStart > 0 && start > 0 && end > start && addressEnd > addressStart) {
                List<String> addList = this.getStrList().subList(addressStart, addressEnd + 1);
                String addressAll = String.join("", addList);
                if (addressAll.length() < 3) return;
                this.address = addressAll.substring(2);
                List<String> scopeList = this.getStrList().subList(start, end);
                String scopeAll = String.join("", scopeList);
                this.businessScope = scopeAll.replace(addressAll, "").trim();
            }
        }
    }
 
    /**
     * 根据关键词切割补全内容
     */
    public void setOther() {
        List<String> properties = Arrays.asList(TYSHXYDM, "名称", "类型", "法定代表人", "经营范围", "注册资本", "成立日期", "营业期限", "住所", "登记机关");
        Map<String, String> result = extractProperties(this.getContent(), properties);
        for (Map.Entry<String, String> entry : result.entrySet()) {
            switch (entry.getKey()) {
                case TYSHXYDM:
                    this.code = entry.getValue();
                    break;
                case "名称":
                    this.name = entry.getValue();
                    break;
                case "类型":
                    this.businessType = entry.getValue();
                    break;
                case "法定代表人":
                    this.userName = entry.getValue();
                    break;
                case "经营范围":
                    this.businessScope = entry.getValue();
                    break;
                case "注册资本":
                    this.capital = entry.getValue();
                    break;
                case "成立日期":
                    this.createDate = DateUtil.checkDate(entry.getValue(), "yyyy年MM月dd日").getTime();
                    break;
                case "营业期限":
                    this.timeLimit = entry.getValue();
                    break;
                case "住所":
                    this.address = entry.getValue();
                    break;
                default:
                    break;
            }
        }
    }
 
    /**
     * 整体切割
     *
     * @param input
     * @param propertyNames
     * @return
     */
    public static Map<String, String> extractProperties(String input, List<String> propertyNames) {
        // 存储属性和它们的起始位置
        Map<String, Integer> propertyPositions = new HashMap<>();
        Map<String, String> result = new LinkedHashMap<>();
 
        // 查找每个属性的位置
        for (String property : propertyNames) {
            int index = input.indexOf(property);
            if (index != -1) {
                propertyPositions.put(property, index);
            }
        }
 
        // 如果没有找到任何属性,返回空map
        if (propertyPositions.isEmpty()) {
            return result;
        }
 
        // 按位置排序属性
        List<Map.Entry<String, Integer>> sortedEntries = new ArrayList<>(propertyPositions.entrySet());
        sortedEntries.sort(Map.Entry.comparingByValue());
 
        // 提取每个属性的内容
        for (int i = 0; i < sortedEntries.size(); i++) {
            String currentProperty = sortedEntries.get(i).getKey();
            int startPos = sortedEntries.get(i).getValue() + currentProperty.length();
 
            // 确定结束位置(下一个属性的开始位置或字符串末尾)
            int endPos = (i < sortedEntries.size() - 1)
                    ? sortedEntries.get(i + 1).getValue()
                    : input.length();
 
            // 提取内容并去除可能的冒号、空格等
            String content = input.substring(startPos, endPos).trim();
            content = content.replaceAll("^[::\\s]+", "").trim();
 
            result.put(currentProperty, content);
        }
 
        return result;
    }
}