1215 lines
39 KiB
JavaScript
1215 lines
39 KiB
JavaScript
// ==UserScript==
|
|
// @name 爱企查&企查查等
|
|
// @namespace http://tampermonkey.net/
|
|
// @version 0.2
|
|
// @description 在页面右下角添加工具按钮,支持复制源码和解析公司信息
|
|
// @author You
|
|
// @match https://www.qcc.com/firm/*
|
|
// @match https://aiqicha.baidu.com/company_detail_*
|
|
// @match https://www.tianyancha.com/company/*
|
|
// @match https://shiming.gsxt.gov.cn/*
|
|
// @grant GM_setClipboard
|
|
// @run-at document-start
|
|
// ==/UserScript==
|
|
|
|
(function () {
|
|
"use strict";
|
|
|
|
// 工具类 - 存放通用函数
|
|
class ToolUtils {
|
|
static cleanText(text) {
|
|
return text
|
|
.replace(/\s+/g, " ")
|
|
.replace(/[\r\n\t]/g, "")
|
|
.trim();
|
|
}
|
|
|
|
static extractText(doc, selectors) {
|
|
for (const selector of selectors) {
|
|
const element = doc.querySelector(selector);
|
|
if (element && element.textContent.trim()) {
|
|
return element.textContent.trim();
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
|
|
static copyToClipboard(content, successMessage) {
|
|
const textarea = document.createElement("textarea");
|
|
textarea.value = content;
|
|
textarea.style.position = "fixed";
|
|
textarea.style.top = "0";
|
|
textarea.style.left = "0";
|
|
textarea.style.width = "1px";
|
|
textarea.style.height = "1px";
|
|
textarea.style.opacity = "0";
|
|
|
|
document.body.appendChild(textarea);
|
|
textarea.select();
|
|
document.execCommand("copy");
|
|
document.body.removeChild(textarea);
|
|
|
|
if (successMessage) {
|
|
this.showAutoCloseMessage(successMessage, "success");
|
|
|
|
}
|
|
}
|
|
|
|
static showAutoCloseMessage(message, type = "info") {
|
|
// 创建一个自动关闭的提示框替代 alert
|
|
const alertBox = document.createElement("div");
|
|
alertBox.textContent = message;
|
|
alertBox.style.position = "fixed";
|
|
alertBox.style.top = "50%";
|
|
alertBox.style.left = "50%";
|
|
alertBox.style.transform = "translate(-50%, -50%)";
|
|
|
|
// 根据消息类型设置不同颜色
|
|
if (type === "success") {
|
|
alertBox.style.backgroundColor = "#52c41a";
|
|
} else if (type === "error") {
|
|
alertBox.style.backgroundColor = "#f5222d";
|
|
} else {
|
|
alertBox.style.backgroundColor = "#1890ff";
|
|
}
|
|
|
|
alertBox.style.color = "white";
|
|
alertBox.style.padding = "10px 20px";
|
|
alertBox.style.borderRadius = "4px";
|
|
alertBox.style.zIndex = "10001";
|
|
alertBox.style.boxShadow = "0 2px 8px rgba(0,0,0,0.15)";
|
|
alertBox.style.transition = "opacity 0.3s";
|
|
|
|
document.body.appendChild(alertBox);
|
|
|
|
// 2秒后自动关闭
|
|
setTimeout(() => {
|
|
if (document.body.contains(alertBox)) {
|
|
// 添加淡出效果
|
|
alertBox.style.opacity = "0";
|
|
// 真正移除元素
|
|
setTimeout(() => {
|
|
if (document.body.contains(alertBox)) {
|
|
document.body.removeChild(alertBox);
|
|
}
|
|
}, 300);
|
|
}
|
|
}, 2000);
|
|
}
|
|
|
|
static showResult(data) {
|
|
const modal = document.createElement("div");
|
|
modal.style.position = "fixed";
|
|
modal.style.top = "50%";
|
|
modal.style.left = "50%";
|
|
modal.style.transform = "translate(-50%, -50%)";
|
|
modal.style.width = "600px";
|
|
modal.style.maxHeight = "80vh";
|
|
modal.style.overflowY = "auto";
|
|
modal.style.backgroundColor = "white";
|
|
modal.style.padding = "20px";
|
|
modal.style.boxShadow = "0 0 10px rgba(0,0,0,0.3)";
|
|
modal.style.zIndex = "10000";
|
|
|
|
const pre = document.createElement("pre");
|
|
pre.textContent = JSON.stringify(data, null, 2);
|
|
pre.style.whiteSpace = "pre-wrap";
|
|
pre.style.wordWrap = "break-word";
|
|
|
|
const copyBtn = document.createElement("button");
|
|
copyBtn.textContent = "复制JSON";
|
|
copyBtn.style.marginTop = "10px";
|
|
copyBtn.style.padding = "8px 16px";
|
|
copyBtn.style.backgroundColor = "#52c41a";
|
|
copyBtn.style.color = "white";
|
|
copyBtn.style.border = "none";
|
|
copyBtn.style.borderRadius = "4px";
|
|
copyBtn.style.cursor = "pointer";
|
|
|
|
copyBtn.addEventListener("click", () => {
|
|
navigator.clipboard
|
|
.writeText(JSON.stringify(data, null, 2))
|
|
.then(() => this.showAutoCloseMessage("已复制到剪贴板", "success"))
|
|
.catch((err) => alert("复制失败: " + err));
|
|
});
|
|
|
|
const closeBtn = document.createElement("button");
|
|
closeBtn.textContent = "关闭";
|
|
closeBtn.style.marginLeft = "10px";
|
|
closeBtn.style.marginTop = "10px";
|
|
closeBtn.style.padding = "8px 16px";
|
|
closeBtn.style.backgroundColor = "#f5222d";
|
|
closeBtn.style.color = "white";
|
|
closeBtn.style.border = "none";
|
|
closeBtn.style.borderRadius = "4px";
|
|
closeBtn.style.cursor = "pointer";
|
|
|
|
closeBtn.addEventListener("click", () => {
|
|
document.body.removeChild(modal);
|
|
});
|
|
|
|
modal.innerHTML = '<h2 style="margin-top: 0;">企业信息解析结果</h2>';
|
|
modal.appendChild(pre);
|
|
modal.appendChild(document.createElement("br"));
|
|
modal.appendChild(copyBtn);
|
|
modal.appendChild(closeBtn);
|
|
|
|
document.body.appendChild(modal);
|
|
// // Automatically close the modal after 2 seconds
|
|
// setTimeout(() => {
|
|
// if (document.body.contains(modal)) {
|
|
// document.body.removeChild(modal);
|
|
// }
|
|
// }, 2000);
|
|
}
|
|
}
|
|
|
|
// 爱企查解析类
|
|
class AiQiChaParser {
|
|
getPhoneNumber() {
|
|
// 查找电话信息容器
|
|
const phoneContainer = document.querySelector(
|
|
"div.business-info div.telphone-lists-wrap"
|
|
);
|
|
if (!phoneContainer) return "未找到电话信息";
|
|
|
|
// 查找包含电话号码的元素
|
|
const phoneElement = phoneContainer.querySelector("span.copy-box span");
|
|
if (!phoneElement) return "未找到电话号码";
|
|
|
|
return ToolUtils.cleanText(phoneElement.textContent);
|
|
}
|
|
constructor() {
|
|
this.table = null;
|
|
}
|
|
|
|
// 初始化表格
|
|
initTable() {
|
|
this.table = document.querySelector("table.zx-detail-basic-table");
|
|
if (!this.table) {
|
|
alert("未找到企业信息表格");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// 获取优化后的值
|
|
getOptimizedValue(title) {
|
|
const cells = Array.from(this.table.querySelectorAll("td"));
|
|
const titleCell = cells.find(
|
|
(cell) => ToolUtils.cleanText(cell.textContent) === title
|
|
);
|
|
|
|
if (!titleCell) return null;
|
|
|
|
let valueCell = titleCell.nextElementSibling;
|
|
if (!valueCell) return null;
|
|
|
|
const valueElement =
|
|
valueCell.querySelector(".enter-bg-ele") ||
|
|
valueCell.querySelector(".addr-enter-bg-ele") ||
|
|
valueCell;
|
|
|
|
return ToolUtils.cleanText(valueElement.textContent);
|
|
}
|
|
|
|
// 获取法定代表人
|
|
getLegalRepresentative() {
|
|
|
|
// First check for 经营者 (operator) which is used for individual businesses
|
|
const operatorElements = Array.from(
|
|
this.table.querySelectorAll("td")
|
|
).filter((td) => (ToolUtils.cleanText(td.textContent) === "经营者") ||
|
|
ToolUtils.cleanText(td.textContent) === "执行事务合伙人" ||
|
|
ToolUtils.cleanText(td.textContent) === "负责人" ||
|
|
ToolUtils.cleanText(td.textContent) === "法定代表人"
|
|
);
|
|
|
|
if (operatorElements.length > 0) {
|
|
const valueCell = operatorElements[0].nextElementSibling;
|
|
if (valueCell) {
|
|
// Check if it has the image-text-content structure
|
|
if (valueCell.classList.contains("image-text-content")) {
|
|
const nameElement = valueCell.querySelector(".person-name-warp a");
|
|
if (nameElement) {
|
|
return ToolUtils.cleanText(nameElement.textContent);
|
|
}
|
|
return ToolUtils.cleanText(valueCell.textContent);
|
|
}
|
|
// Regular structure
|
|
return ToolUtils.cleanText(valueCell.textContent);
|
|
}
|
|
}
|
|
|
|
// 备用查找方式
|
|
const titleElements = Array.from(
|
|
this.table.querySelectorAll("td")
|
|
).filter((td) => td.textContent.includes("法定代表人"));
|
|
|
|
if (titleElements.length > 0 && titleElements[0].nextElementSibling) {
|
|
const valueCell = titleElements[0].nextElementSibling;
|
|
return ToolUtils.cleanText(valueCell.textContent);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
// 获取统一社会信用代码
|
|
getUnifiedSocialCreditCode() {
|
|
const codeElements = Array.from(this.table.querySelectorAll("td")).filter(
|
|
(td) => {
|
|
return (
|
|
td.textContent.includes("统一社会信用代码") &&
|
|
td.nextElementSibling &&
|
|
td.nextElementSibling.classList.contains("table-regCapital-lable")
|
|
);
|
|
}
|
|
);
|
|
|
|
if (codeElements.length > 0) {
|
|
const valueCell = codeElements[0].nextElementSibling;
|
|
const rawValue =
|
|
valueCell.querySelector(".enter-bg-ele")?.textContent ||
|
|
valueCell.textContent;
|
|
return ToolUtils.cleanText(rawValue);
|
|
}
|
|
|
|
const taxElements = Array.from(this.table.querySelectorAll("td")).filter(
|
|
(td) => td.textContent.includes("纳税人识别号")
|
|
);
|
|
|
|
if (taxElements.length > 0 && taxElements[0].nextElementSibling) {
|
|
const valueCell = taxElements[0].nextElementSibling;
|
|
const rawValue =
|
|
valueCell.querySelector(".enter-bg-ele")?.textContent ||
|
|
valueCell.textContent;
|
|
return ToolUtils.cleanText(rawValue);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
// 获取工商注册号
|
|
getBusinessRegistrationNo() {
|
|
const regElements = Array.from(this.table.querySelectorAll("td")).filter(
|
|
(td) => ToolUtils.cleanText(td.textContent).includes("工商注册号")
|
|
);
|
|
|
|
if (regElements.length > 0 && regElements[0].nextElementSibling) {
|
|
const valueCell = regElements[0].nextElementSibling;
|
|
const rawValue =
|
|
valueCell.querySelector(".enter-bg-ele")?.textContent ||
|
|
valueCell.textContent;
|
|
return ToolUtils.cleanText(rawValue);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
// 获取组织机构代码
|
|
getOrganizationCode() {
|
|
const orgCodeElements = Array.from(
|
|
this.table.querySelectorAll(".poptip-wrap-org-no")
|
|
).filter((el) => el.textContent.includes("组织机构代码"));
|
|
|
|
if (orgCodeElements.length > 0) {
|
|
const valueCell = orgCodeElements[0].closest("td").nextElementSibling;
|
|
if (valueCell && valueCell.classList.contains("enter-bg")) {
|
|
const rawValue =
|
|
valueCell.querySelector(".enter-bg-ele")?.textContent ||
|
|
valueCell.textContent;
|
|
return ToolUtils.cleanText(rawValue);
|
|
}
|
|
}
|
|
|
|
const titleElements = Array.from(
|
|
this.table.querySelectorAll("td")
|
|
).filter((td) => ToolUtils.cleanText(td.textContent) === "组织机构代码");
|
|
|
|
if (titleElements.length > 0 && titleElements[0].nextElementSibling) {
|
|
const valueCell = titleElements[0].nextElementSibling;
|
|
const rawValue =
|
|
valueCell.querySelector(".enter-bg-ele")?.textContent ||
|
|
valueCell.textContent;
|
|
return ToolUtils.cleanText(rawValue);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
// 获取纳税人识别号
|
|
getTaxpayerId() {
|
|
const taxElements = Array.from(this.table.querySelectorAll("td")).filter(
|
|
(td) => ToolUtils.cleanText(td.textContent).includes("纳税人识别号")
|
|
);
|
|
|
|
if (taxElements.length > 0 && taxElements[0].nextElementSibling) {
|
|
const valueCell = taxElements[0].nextElementSibling;
|
|
const rawValue =
|
|
valueCell.querySelector(".enter-bg-ele")?.textContent ||
|
|
valueCell.textContent;
|
|
return ToolUtils.cleanText(rawValue);
|
|
}
|
|
|
|
const creditElements = Array.from(
|
|
this.table.querySelectorAll("td")
|
|
).filter((td) =>
|
|
ToolUtils.cleanText(td.textContent).includes("统一社会信用代码")
|
|
);
|
|
|
|
if (creditElements.length > 0 && creditElements[0].nextElementSibling) {
|
|
const valueCell = creditElements[0].nextElementSibling;
|
|
const rawValue =
|
|
valueCell.querySelector(".enter-bg-ele")?.textContent ||
|
|
valueCell.textContent;
|
|
return ToolUtils.cleanText(rawValue);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
// 获取参保人数
|
|
getInsuranceNumber() {
|
|
const insuranceElements = Array.from(
|
|
this.table.querySelectorAll("td")
|
|
).filter((td) => {
|
|
return (
|
|
td.textContent.includes("参保人数") &&
|
|
td.querySelector(".insurance-info")
|
|
);
|
|
});
|
|
|
|
if (insuranceElements.length > 0) {
|
|
const valueCell = insuranceElements[0].nextElementSibling;
|
|
if (!valueCell) return null;
|
|
|
|
const rawText = valueCell.textContent.replace(/[\r\n\t]/g, "").trim();
|
|
const match = rawText.match(/(\d+人)/);
|
|
return match ? match[0] : null;
|
|
}
|
|
|
|
const registrationElements = Array.from(
|
|
this.table.querySelectorAll("td")
|
|
).filter((td) => td.textContent.includes("登记机关"));
|
|
|
|
if (
|
|
registrationElements.length > 0 &&
|
|
registrationElements[0].previousElementSibling
|
|
) {
|
|
const valueCell = registrationElements[0].previousElementSibling;
|
|
const rawText = valueCell.textContent.replace(/[\r\n\t]/g, "").trim();
|
|
const match = rawText.match(/(\d+人)/);
|
|
return match ? match[0] : null;
|
|
}
|
|
|
|
// 尝试查找其他可能包含员工数的字段
|
|
const employeeElements = Array.from(
|
|
this.table.querySelectorAll("td")
|
|
).filter((td) =>
|
|
td.textContent.includes("人员规模") ||
|
|
td.textContent.includes("员工人数")
|
|
);
|
|
|
|
if (employeeElements.length > 0 && employeeElements[0].nextElementSibling) {
|
|
const valueCell = employeeElements[0].nextElementSibling;
|
|
const rawText = valueCell.textContent.replace(/[\r\n\t]/g, "").trim();
|
|
return rawText;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
// 获取核准日期
|
|
getApprovalDate() {
|
|
const approvalElements = Array.from(
|
|
this.table.querySelectorAll(".poptip-wrap-annual-date")
|
|
).filter((el) => el.textContent.includes("核准日期"));
|
|
|
|
if (approvalElements.length > 0) {
|
|
const valueCell = approvalElements[0].closest("td").nextElementSibling;
|
|
if (valueCell) {
|
|
const rawValue = valueCell.textContent
|
|
.replace(/[\r\n\t]/g, "")
|
|
.trim();
|
|
if (/^\d{4}-\d{2}-\d{2}$/.test(rawValue)) {
|
|
return rawValue;
|
|
}
|
|
}
|
|
}
|
|
|
|
const titleElements = Array.from(
|
|
this.table.querySelectorAll("td")
|
|
).filter((td) => ToolUtils.cleanText(td.textContent) === "核准日期");
|
|
|
|
if (titleElements.length > 0 && titleElements[0].nextElementSibling) {
|
|
const valueCell = titleElements[0].nextElementSibling;
|
|
const rawValue = ToolUtils.cleanText(valueCell.textContent);
|
|
if (/^\d{4}-\d{2}-\d{2}$/.test(rawValue)) {
|
|
return rawValue;
|
|
}
|
|
}
|
|
|
|
// 如果没有核准日期,尝试使用成立日期作为替代
|
|
const establishmentDate = this.getOptimizedValue("成立日期");
|
|
if (establishmentDate && /^\d{4}-\d{2}-\d{2}$/.test(establishmentDate)) {
|
|
return establishmentDate;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
// 解析公司信息主方法
|
|
parseCompanyInfo() {
|
|
if (!this.initTable()) return;
|
|
|
|
const companyData = {
|
|
企业名称: this.getOptimizedValue("企业名称"),
|
|
统一社会信用代码: this.getUnifiedSocialCreditCode(),
|
|
法定代表人: this.getLegalRepresentative(),
|
|
电话: this.getPhoneNumber(),
|
|
经营状态: this.getOptimizedValue("经营状态"),
|
|
成立日期: this.getOptimizedValue("成立日期"),
|
|
行政区划: this.getOptimizedValue("行政区划"),
|
|
注册资本: this.getOptimizedValue("注册资本"),
|
|
实缴资本: this.getOptimizedValue("实缴资本"),
|
|
企业类型: this.getOptimizedValue("企业类型"),
|
|
所属行业: this.getOptimizedValue("所属行业"),
|
|
工商注册号: this.getBusinessRegistrationNo(),
|
|
组织机构代码: this.getOrganizationCode(),
|
|
纳税人识别号: this.getTaxpayerId(),
|
|
纳税人资质: this.getOptimizedValue("纳税人资质"),
|
|
营业期限: this.getOptimizedValue("营业期限"),
|
|
核准日期: this.getApprovalDate(),
|
|
参保人数: this.getInsuranceNumber(),
|
|
登记机关: this.getOptimizedValue("登记机关"),
|
|
曾用名: this.getOptimizedValue("曾用名"),
|
|
注册地址: this.getOptimizedValue("注册地址"),
|
|
经营范围: this.getOptimizedValue("经营范围"),
|
|
};
|
|
|
|
ToolUtils.showResult(companyData);
|
|
}
|
|
}
|
|
|
|
// QCC解析类 企查查
|
|
class QCCParser {
|
|
constructor() {
|
|
this.table = null;
|
|
}
|
|
|
|
// 初始化表格
|
|
initTable() {
|
|
const cominfoNormal = document.querySelector("div.cominfo-normal");
|
|
if (!cominfoNormal) {
|
|
alert("未找到企业信息容器");
|
|
return false;
|
|
}
|
|
|
|
this.table = cominfoNormal.querySelector("table.ntable");
|
|
if (!this.table) {
|
|
alert("未找到企业信息表格");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// 获取优化后的值
|
|
getOptimizedValue(title) {
|
|
const headerCells = Array.from(this.table.querySelectorAll("td.tb"));
|
|
let value = null;
|
|
|
|
headerCells.forEach((header) => {
|
|
if (ToolUtils.cleanText(header.textContent).includes(title)) {
|
|
const valueCell = header.nextElementSibling;
|
|
if (valueCell) {
|
|
// 尝试从copy-value类中获取值
|
|
const copyValue = valueCell.querySelector(".copy-value");
|
|
if (copyValue) {
|
|
value = ToolUtils.cleanText(copyValue.textContent);
|
|
} else {
|
|
value = ToolUtils.cleanText(valueCell.textContent);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
return value;
|
|
}
|
|
|
|
// 获取法定代表人
|
|
getLegalRepresentative() {
|
|
// Try the existing method first
|
|
const basicValue =
|
|
this.getOptimizedValue("法定代表人") || this.getOptimizedValue("法人");
|
|
if (basicValue && basicValue.trim()) {
|
|
// Remove any "关联企业 X" text
|
|
return basicValue.replace(/\s*关联企业\s*\d+$/, "").trim();
|
|
}
|
|
|
|
// If basic extraction fails, try more specific approach
|
|
const headerCell = Array.from(this.table.querySelectorAll("td.tb")).find(
|
|
(cell) => ToolUtils.cleanText(cell.textContent).includes("法定代表人")
|
|
);
|
|
|
|
if (!headerCell) return null;
|
|
|
|
const valueCell = headerCell.nextElementSibling;
|
|
if (!valueCell) return null;
|
|
|
|
// Try to find the name within the complex structure
|
|
// Look for anchor tags with target="_blank" which typically contain the legal representative's name
|
|
const nameLinks = valueCell.querySelectorAll('a[target="_blank"]');
|
|
for (const link of nameLinks) {
|
|
const name = ToolUtils.cleanText(link.textContent);
|
|
// Make sure it's not empty and doesn't contain obvious non-name text
|
|
if (name && !name.includes("关联企业") && !name.includes("复制")) {
|
|
return name;
|
|
}
|
|
}
|
|
|
|
// Alternative approach - look for the first anchor tag in the cell
|
|
const firstLink = valueCell.querySelector("a");
|
|
if (firstLink) {
|
|
const name = ToolUtils.cleanText(firstLink.textContent);
|
|
// Remove any trailing "关联企业 X" text
|
|
return name.replace(/\s*关联企业\s*\d+$/, "").trim();
|
|
}
|
|
|
|
// Fallback to general value extraction
|
|
const copyValue = valueCell.querySelector(".copy-value");
|
|
if (copyValue) {
|
|
const name = ToolUtils.cleanText(copyValue.textContent);
|
|
// Remove any trailing "关联企业 X" text
|
|
return name.replace(/\s*关联企业\s*\d+$/, "").trim();
|
|
}
|
|
|
|
const rawText = ToolUtils.cleanText(valueCell.textContent);
|
|
// Remove any trailing "关联企业 X" text
|
|
return rawText.replace(/\s*关联企业\s*\d+$/, "").trim();
|
|
}
|
|
|
|
// 获取统一社会信用代码
|
|
getUnifiedSocialCreditCode() {
|
|
return (
|
|
this.getOptimizedValue("统一社会信用代码") ||
|
|
this.getOptimizedValue("信用代码")
|
|
);
|
|
}
|
|
|
|
// 获取工商注册号
|
|
getBusinessRegistrationNo() {
|
|
return (
|
|
this.getOptimizedValue("工商注册号") || this.getOptimizedValue("注册号")
|
|
);
|
|
}
|
|
|
|
// 获取组织机构代码
|
|
getOrganizationCode() {
|
|
return this.getOptimizedValue("组织机构代码");
|
|
}
|
|
|
|
// 获取纳税人识别号
|
|
getTaxpayerId() {
|
|
return (
|
|
this.getOptimizedValue("纳税人识别号") ||
|
|
this.getUnifiedSocialCreditCode()
|
|
);
|
|
}
|
|
|
|
// 获取参保人数
|
|
getInsuranceNumber() {
|
|
// 查找参保人数表头
|
|
const headerCell = Array.from(this.table.querySelectorAll("td.tb")).find(
|
|
(cell) => ToolUtils.cleanText(cell.textContent).includes("参保人数")
|
|
);
|
|
|
|
if (!headerCell) return null;
|
|
|
|
const valueCell = headerCell.nextElementSibling;
|
|
if (!valueCell) return null;
|
|
|
|
// 提取参保人数数字
|
|
const numberSpan = valueCell.querySelector("span");
|
|
const number = numberSpan
|
|
? ToolUtils.cleanText(numberSpan.textContent)
|
|
: null;
|
|
|
|
// 提取年报年份
|
|
const reportLink = valueCell.querySelector("a.m-l-r-10");
|
|
const reportYear = reportLink
|
|
? ToolUtils.cleanText(reportLink.textContent)
|
|
: "";
|
|
|
|
// 组合结果
|
|
return number ? `${number}人 ${reportYear}` : null;
|
|
}
|
|
|
|
// 获取联系电话
|
|
getPhoneNumber() {
|
|
// 查找联系信息容器
|
|
const contactInfo = document.querySelector("div.contact-info");
|
|
if (!contactInfo) return null;
|
|
|
|
// 查找右侧信息区域
|
|
const rightPart = contactInfo.querySelector("div.main-part-item.right");
|
|
if (!rightPart) return null;
|
|
|
|
// 查找包含电话的行
|
|
const rows = Array.from(rightPart.querySelectorAll("div.rline"));
|
|
const phoneRow = rows.find((row) =>
|
|
ToolUtils.cleanText(row.textContent).includes("电话:")
|
|
);
|
|
|
|
if (!phoneRow) return null;
|
|
|
|
// 提取电话号码
|
|
const spans = Array.from(
|
|
phoneRow.querySelectorAll("span.need-copy-field")
|
|
);
|
|
const phoneSpan = spans.find(
|
|
(span) => !ToolUtils.cleanText(span.textContent).includes("电话:")
|
|
);
|
|
|
|
return phoneSpan ? ToolUtils.cleanText(phoneSpan.textContent) : null;
|
|
}
|
|
|
|
// 获取核准日期
|
|
getApprovalDate() {
|
|
return (
|
|
this.getOptimizedValue("核准日期") || this.getOptimizedValue("成立日期")
|
|
);
|
|
}
|
|
|
|
// 解析公司信息主方法
|
|
parseCompanyInfo() {
|
|
if (!this.initTable()) return;
|
|
|
|
const companyData = {
|
|
企业名称:
|
|
this.getOptimizedValue("企业名称") ||
|
|
this.getOptimizedValue("公司名称"),
|
|
统一社会信用代码: this.getUnifiedSocialCreditCode(),
|
|
法定代表人: this.getLegalRepresentative(),
|
|
经营状态: this.getOptimizedValue("登记状态"),
|
|
成立日期: this.getOptimizedValue("成立日期"),
|
|
行政区划: this.getOptimizedValue("行政区划"),
|
|
注册资本: this.getOptimizedValue("注册资本"),
|
|
实缴资本: this.getOptimizedValue("实缴资本"),
|
|
企业类型: this.getOptimizedValue("企业类型"),
|
|
所属行业: this.getOptimizedValue("国标行业"),
|
|
工商注册号: this.getBusinessRegistrationNo(),
|
|
组织机构代码: this.getOrganizationCode(),
|
|
纳税人识别号: this.getTaxpayerId(),
|
|
纳税人资质: this.getOptimizedValue("纳税人资质"),
|
|
营业期限: this.getOptimizedValue("营业期限"),
|
|
核准日期: this.getApprovalDate(),
|
|
参保人数: this.getInsuranceNumber(),
|
|
电话: this.getPhoneNumber(),
|
|
登记机关: this.getOptimizedValue("登记机关"),
|
|
曾用名: this.getOptimizedValue("曾用名"),
|
|
注册地址: this.getOptimizedValue("注册地址"),
|
|
经营范围: this.getOptimizedValue("经营范围"),
|
|
};
|
|
|
|
ToolUtils.showResult(companyData);
|
|
}
|
|
}
|
|
|
|
|
|
// 国家企业信用信息公示系统解析类
|
|
// 国家企业信用信息公示系统解析类
|
|
class NationalCreditParser {
|
|
constructor() {
|
|
this.infoContainer = null;
|
|
}
|
|
|
|
// 初始化信息容器
|
|
initContainer() {
|
|
this.infoContainer = document.querySelector("#primaryInfo .overview");
|
|
if (!this.infoContainer) {
|
|
alert("未找到企业信息容器");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// 获取优化后的值
|
|
getOptimizedValue(title) {
|
|
const dls = Array.from(this.infoContainer.querySelectorAll("dl"));
|
|
for (const dl of dls) {
|
|
const dt = dl.querySelector("dt");
|
|
if (dt && ToolUtils.cleanText(dt.textContent).includes(title)) {
|
|
const dd = dl.querySelector("dd");
|
|
if (dd) {
|
|
return ToolUtils.cleanText(dd.textContent);
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// 获取企业名称
|
|
getCompanyName() {
|
|
return this.getOptimizedValue("企业名称");
|
|
}
|
|
|
|
// 获取统一社会信用代码
|
|
getUnifiedSocialCreditCode() {
|
|
return this.getOptimizedValue("统一社会信用代码");
|
|
}
|
|
|
|
// 获取法定代表人
|
|
getLegalRepresentative() {
|
|
return this.getOptimizedValue("法定代表人");
|
|
}
|
|
|
|
// 获取成立日期
|
|
getEstablishmentDate() {
|
|
return this.getOptimizedValue("成立日期");
|
|
}
|
|
|
|
// 获取注册资本
|
|
getRegisteredCapital() {
|
|
return this.getOptimizedValue("注册资本");
|
|
}
|
|
|
|
// 获取企业类型
|
|
getEnterpriseType() {
|
|
return this.getOptimizedValue("类型");
|
|
}
|
|
|
|
// 获取核准日期
|
|
getApprovalDate() {
|
|
return this.getOptimizedValue("核准日期");
|
|
}
|
|
|
|
// 获取登记机关
|
|
getRegistrationAuthority() {
|
|
return this.getOptimizedValue("登记机关");
|
|
}
|
|
|
|
// 获取经营状态
|
|
getBusinessStatus() {
|
|
return this.getOptimizedValue("登记状态");
|
|
}
|
|
|
|
// 获取住所/注册地址
|
|
getRegisteredAddress() {
|
|
// return this.getOptimizedValue("住所");
|
|
// 主要查找方式
|
|
const address = this.getOptimizedValue("注册地址");
|
|
if (address) {
|
|
return address;
|
|
}
|
|
|
|
// 备用查找方式
|
|
const alternativeElements = Array.from(
|
|
this.table.querySelectorAll("td")
|
|
).filter((td) =>
|
|
ToolUtils.cleanText(td.textContent).includes("住所") ||
|
|
ToolUtils.cleanText(td.textContent).includes("营业地址") ||
|
|
ToolUtils.cleanText(td.textContent).includes("办公地址")
|
|
);
|
|
|
|
if (alternativeElements.length > 0 && alternativeElements[0].nextElementSibling) {
|
|
const valueCell = alternativeElements[0].nextElementSibling;
|
|
const valueElement =
|
|
valueCell.querySelector(".enter-bg-ele") ||
|
|
valueCell.querySelector(".addr-enter-bg-ele") ||
|
|
valueCell;
|
|
|
|
const addressText = ToolUtils.cleanText(valueElement.textContent);
|
|
if (addressText) {
|
|
return addressText;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
// 获取经营范围
|
|
getBusinessScope() {
|
|
const dls = Array.from(this.infoContainer.querySelectorAll("dl"));
|
|
for (const dl of dls) {
|
|
const dt = dl.querySelector("dt");
|
|
if (dt && ToolUtils.cleanText(dt.textContent).includes("经营范围")) {
|
|
const dd = dl.querySelector("dd");
|
|
if (dd) {
|
|
// For business scope, we want to preserve more formatting
|
|
return dd.textContent.trim().replace(/[\r\n\t]+/g, " ").replace(/\s+/g, " ");
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// 解析公司信息主方法
|
|
parseCompanyInfo() {
|
|
if (!this.initContainer()) return;
|
|
|
|
const companyData = {
|
|
企业名称: this.getCompanyName(),
|
|
统一社会信用代码: this.getUnifiedSocialCreditCode(),
|
|
法定代表人: this.getLegalRepresentative(),
|
|
经营状态: this.getBusinessStatus(),
|
|
成立日期: this.getEstablishmentDate(),
|
|
注册资本: this.getRegisteredCapital(),
|
|
企业类型: this.getEnterpriseType(),
|
|
核准日期: this.getApprovalDate(),
|
|
登记机关: this.getRegistrationAuthority(),
|
|
注册地址: this.getRegisteredAddress(),
|
|
经营范围: this.getBusinessScope(),
|
|
};
|
|
|
|
ToolUtils.showResult(companyData);
|
|
}
|
|
}
|
|
// end国家企业信用信息公示系统解析类
|
|
// 天眼查解析类
|
|
// 天眼查解析类
|
|
class TianYanChaParser {
|
|
constructor() {
|
|
this.container = null;
|
|
}
|
|
|
|
// 初始化容器
|
|
initContainer() {
|
|
// 使用正确的容器选择器
|
|
this.container = document.querySelector(".index_tableBox__ZadJW");
|
|
if (!this.container) {
|
|
alert("未找到企业信息容器");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// 获取法定代表人
|
|
getLegalRepresentative() {
|
|
const legalElement = document.querySelector(".index_legal-representative__Kfdqv a.link-click");
|
|
if (legalElement) {
|
|
return ToolUtils.cleanText(legalElement.textContent);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// 从表格中获取值
|
|
getValueByLabel(label,includeOnlyTextNode=false) {
|
|
const rows = Array.from(document.querySelectorAll("tr"));
|
|
for (const row of rows) {
|
|
const cells = Array.from(row.children);
|
|
for (let i = 0; i < cells.length; i++) {
|
|
const cellText = ToolUtils.cleanText(cells[i].textContent);
|
|
if (cellText.includes(label)) {
|
|
// 查找下一个单元格作为值
|
|
const nextCell = cells[i + 1];
|
|
if (nextCell) {
|
|
if(includeOnlyTextNode){
|
|
// Extract only direct text content, excluding nested divs
|
|
let directText = '';
|
|
for (const node of nextCell.childNodes) {
|
|
// directText+='node text:'+node.textContent+', type:'+ node.nodeType+'\n';
|
|
// console.log('node:',node,' node type:',node.nodeType," node.textContent:",node.textContent);
|
|
// Only include text nodes and exclude elements with classes
|
|
if (node.nodeType === Node.TEXT_NODE) {
|
|
directText += node.textContent;
|
|
}
|
|
}
|
|
return ToolUtils.cleanText(directText);
|
|
}else{
|
|
// 处理包含复制按钮的特殊结构
|
|
const copyBox = nextCell.querySelector(".index_copy-box__7b6Aq");
|
|
if (copyBox) {
|
|
const copyText = copyBox.querySelector(".index_copy-text__ri7W6");
|
|
if (copyText) {
|
|
return ToolUtils.cleanText(copyText.textContent);
|
|
}
|
|
}
|
|
return ToolUtils.cleanText(nextCell.textContent);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// 获取统一社会信用代码
|
|
getUnifiedSocialCreditCode() {
|
|
return this.getValueByLabel("统一社会信用代码");
|
|
}
|
|
|
|
// 获取企业名称
|
|
getCompanyName() {
|
|
const nameElement = document.querySelector("h1.index_company-name__LqKlo .index_name__dz4jY");
|
|
if (nameElement) {
|
|
return ToolUtils.cleanText(nameElement.textContent);
|
|
}
|
|
return this.getValueByLabel("企业名称");
|
|
}
|
|
|
|
// 获取注册资本
|
|
getRegisteredCapital() {
|
|
return this.getValueByLabel("注册资本");
|
|
}
|
|
|
|
// 获取成立日期
|
|
getEstablishmentDate() {
|
|
return this.getValueByLabel("成立日期");
|
|
}
|
|
|
|
// 获取经营状态
|
|
getBusinessStatus() {
|
|
return this.getValueByLabel("登记状态") || this.getValueByLabel("经营状态");
|
|
}
|
|
|
|
// 获取工商注册号
|
|
getBusinessRegistrationNo() {
|
|
return this.getValueByLabel("工商注册号");
|
|
}
|
|
|
|
// 获取组织机构代码
|
|
getOrganizationCode() {
|
|
return this.getValueByLabel("组织机构代码");
|
|
}
|
|
|
|
// 获取纳税人识别号
|
|
getTaxpayerId() {
|
|
return this.getValueByLabel("纳税人识别号");
|
|
}
|
|
|
|
// 获取核准日期
|
|
getApprovalDate() {
|
|
return this.getValueByLabel("核准日期");
|
|
}
|
|
|
|
// 获取登记机关
|
|
getRegistrationAuthority() {
|
|
return this.getValueByLabel("登记机关");
|
|
}
|
|
|
|
// 获取注册地址
|
|
getRegisteredAddress() {
|
|
return this.getValueByLabel("注册地址");
|
|
}
|
|
|
|
// 获取经营范围
|
|
getBusinessScope() {
|
|
return this.getValueByLabel("经营范围");
|
|
}
|
|
|
|
// 获取实缴资本
|
|
getActualCapital() {
|
|
return this.getValueByLabel("实缴资本");
|
|
}
|
|
|
|
// 获取企业类型
|
|
getEnterpriseType() {
|
|
return this.getValueByLabel("企业类型");
|
|
}
|
|
|
|
// 获取参保人数
|
|
getInsuranceNumber() {
|
|
const result = this.getValueByLabel("参保人数",true);
|
|
if (result) {
|
|
// Extract only the first number from the beginning of the string
|
|
// This handles cases where there are additional elements like "2024年报" after the number
|
|
const match = result.match(/^(\d+)/);
|
|
if (match) {
|
|
return match[1] + "人";
|
|
}
|
|
// Fallback to the original regex pattern
|
|
const fallbackMatch = result.match(/(\d+)人/);
|
|
return fallbackMatch ? `${fallbackMatch[1]}人` : null;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// 获取联系电话
|
|
getPhoneNumber() {
|
|
// 查找电话信息
|
|
const phoneElements = document.querySelectorAll(".index_detail-info-item__oAOqL");
|
|
for (const element of phoneElements) {
|
|
const labelText = ToolUtils.cleanText(element.textContent);
|
|
if (labelText.includes("电话")) {
|
|
const phoneSpan = element.querySelector(".link-hover-click");
|
|
if (phoneSpan) {
|
|
return ToolUtils.cleanText(phoneSpan.textContent);
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// 解析公司信息主方法
|
|
parseCompanyInfo() {
|
|
if (!this.initContainer()) return;
|
|
|
|
const companyData = {
|
|
企业名称: this.getCompanyName(),
|
|
统一社会信用代码: this.getUnifiedSocialCreditCode(),
|
|
法定代表人: this.getLegalRepresentative(),
|
|
电话: this.getPhoneNumber(),
|
|
经营状态: this.getBusinessStatus(),
|
|
成立日期: this.getEstablishmentDate(),
|
|
注册资本: this.getRegisteredCapital(),
|
|
实缴资本: this.getActualCapital(),
|
|
企业类型: this.getEnterpriseType(),
|
|
工商注册号: this.getBusinessRegistrationNo(),
|
|
组织机构代码: this.getOrganizationCode(),
|
|
纳税人识别号: this.getTaxpayerId(),
|
|
核准日期: this.getApprovalDate(),
|
|
登记机关: this.getRegistrationAuthority(),
|
|
注册地址: this.getRegisteredAddress(),
|
|
经营范围: this.getBusinessScope(),
|
|
参保人数: this.getInsuranceNumber(),
|
|
};
|
|
|
|
ToolUtils.showResult(companyData);
|
|
}
|
|
}
|
|
// end 天眼查解析类
|
|
|
|
// 创建按钮容器
|
|
function createButtonContainer() {
|
|
const container = document.createElement("div");
|
|
container.id = "tool-container";
|
|
Object.assign(container.style, {
|
|
position: "fixed",
|
|
right: "20px",
|
|
bottom: "20px",
|
|
zIndex: "9999",
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
gap: "10px",
|
|
width: "40px",
|
|
height: "40px",
|
|
backgroundColor: "#4CAF50",
|
|
borderRadius: "50%",
|
|
transition: "all 0.3s ease",
|
|
overflow: "hidden",
|
|
cursor: "move",
|
|
});
|
|
|
|
// +号指示器
|
|
const plusSign = document.createElement("div");
|
|
plusSign.textContent = "+";
|
|
Object.assign(plusSign.style, {
|
|
color: "white",
|
|
fontSize: "24px",
|
|
textAlign: "center",
|
|
lineHeight: "40px",
|
|
width: "100%",
|
|
});
|
|
container.appendChild(plusSign);
|
|
|
|
// 悬停展开效果
|
|
container.addEventListener("mouseenter", () => {
|
|
container.style.width = "150px";
|
|
container.style.height = "auto";
|
|
container.style.borderRadius = "8px";
|
|
});
|
|
|
|
container.addEventListener("mouseleave", () => {
|
|
container.style.width = "40px";
|
|
container.style.height = "40px";
|
|
container.style.borderRadius = "50%";
|
|
});
|
|
|
|
// 添加拖动功能
|
|
let isDragging = false;
|
|
let offsetX, offsetY;
|
|
|
|
// 鼠标按下开始拖动
|
|
container.addEventListener("mousedown", (e) => {
|
|
// 只有点击+号区域才允许拖动
|
|
if (e.target === plusSign || e.target === container) {
|
|
isDragging = true;
|
|
const rect = container.getBoundingClientRect();
|
|
offsetX = e.clientX - rect.left;
|
|
offsetY = e.clientY - rect.top;
|
|
container.style.cursor = "grabbing";
|
|
// 阻止事件冒泡和默认行为
|
|
e.stopPropagation();
|
|
e.preventDefault();
|
|
}
|
|
});
|
|
|
|
// 鼠标移动时更新位置
|
|
document.addEventListener("mousemove", (e) => {
|
|
if (!isDragging) return;
|
|
container.style.left = e.clientX - offsetX + "px";
|
|
container.style.top = e.clientY - offsetY + "px";
|
|
container.style.right = "auto";
|
|
container.style.bottom = "auto";
|
|
});
|
|
|
|
// 鼠标释放结束拖动
|
|
document.addEventListener("mouseup", () => {
|
|
if (isDragging) {
|
|
isDragging = false;
|
|
container.style.cursor = "move";
|
|
}
|
|
});
|
|
// 创建功能按钮
|
|
function createButton(text, onClick) {
|
|
const button = document.createElement("button");
|
|
button.textContent = text;
|
|
Object.assign(button.style, {
|
|
padding: "8px 12px",
|
|
border: "none",
|
|
borderRadius: "4px",
|
|
backgroundColor: "white",
|
|
color: "#333",
|
|
cursor: "pointer",
|
|
width: "100%",
|
|
transition: "backgroundColor 0.2s",
|
|
});
|
|
button.addEventListener(
|
|
"mouseenter",
|
|
() => (button.style.backgroundColor = "#f0f0f0")
|
|
);
|
|
button.addEventListener(
|
|
"mouseleave",
|
|
() => (button.style.backgroundColor = "white")
|
|
);
|
|
button.addEventListener("click", onClick);
|
|
return button;
|
|
}
|
|
|
|
// 复制源码按钮
|
|
const copySourceButton = createButton("复制源码", () => {
|
|
const html = document.documentElement.outerHTML;
|
|
GM_setClipboard(html, 'text');
|
|
ToolUtils.showAutoCloseMessage("源码已复制到剪贴板", "success")
|
|
});
|
|
|
|
// 解析公司信息按钮
|
|
const parseInfoButton = createButton("解析公司信息", () => {
|
|
// 根据当前URL选择对应的解析器
|
|
let parser;
|
|
if (window.location.host.includes("aiqicha.baidu.com")) {
|
|
parser = new AiQiChaParser();
|
|
} else if (window.location.host.includes("qcc.com")) {
|
|
parser = new QCCParser();
|
|
} else if (window.location.host.includes("tianyancha.com")) {
|
|
parser = new TianYanChaParser();
|
|
} else if (window.location.host.includes("gsxt.gov.cn")) {
|
|
parser = new NationalCreditParser();
|
|
} else {
|
|
alert("不支持的网站");
|
|
return;
|
|
}
|
|
parser.parseCompanyInfo();
|
|
});
|
|
|
|
// 添加按钮到容器
|
|
container.appendChild(copySourceButton);
|
|
container.appendChild(parseInfoButton);
|
|
|
|
document.body.appendChild(container);
|
|
}
|
|
|
|
// 页面加载完成后创建按钮
|
|
window.addEventListener("load", createButtonContainer);
|
|
})();
|