把四省市专精特新公示名单抓下来:22,960 条,以及我踩的三个口径坑
起因很简单:我想知道「权威机构发布的名单」这类公开信源,实际能用到什么程度。挑了上海、江苏、安徽、广东四省市 2025 年度的省级专精特新中小企业公示名单,全部抓下来,去重之后 22,960 条。
这一篇记录抓取过程和三个口径坑。结论放在最前面:公示文本里能稳定拿到的字段只有两个——企业名称、所属批次。 字段集决定了它能用来做什么,这个限制比数据量大不大重要得多。
一、数据源怎么找
公示名单挂在各省工信厅或经信委官网上,发布形式不统一。这次遇到的三种:
江苏和安徽是公告页挂附件,附件多为 xls 或 xlsx,比较好处理。
上海分四批发布,每批一个页面,附件有 xls 也有 pdf。
广东是省厅公示加深圳单列公示,深圳那份在市中小企业服务局,需要单独抓。
找文件的办法很笨但有效:在站内搜「专精特新中小企业 公示 2025」,按发布时间排序,逐条看附件后缀。四个省市加起来二十来个文件,手工过一遍比写爬虫快。
二、解析
附件格式不统一,得分开处理。
xls/xlsx 直接用 pandas:
import pandas as pd
def read_list(path):
df = pd.read_excel(path, dtype=str)
df = df.dropna(how="all")
return df
pdf 用 pdfplumber,按行取文本再切列:
import pdfplumber
def read_pdf(path):
rows = []
with pdfplumber.open(path) as pdf:
for page in pdf.pages:
table = page.extract_table()
if table:
rows.extend(table)
return rows
pdf 的麻烦在于表格线和合并单元格,跨页的表头会重复出现,需要在清洗阶段单独处理。这份数据里 pdf 占比不高,我最后是人工抽了一份对照,确认抽取结果和原件一致才继续往下走。
三、去重与清洗
按企业名称去重:
import re
def norm(name: str) -> str:
name = name.replace(" ", "").replace("(", "(").replace(")", ")")
name = re.sub(r"[*\s]", "", name)
return name.strip()
df["key"] = df["企业名称"].map(norm)
df = df.drop_duplicates(subset="key")
全角半角括号、多余空格是最常见的重复来源。这一步做完,四省市合计 22,960 条。
我没有做工商核验。也就是说,重名企业和登记信息变更的情况没有被识别出来,这是这份数据的一个已知缺陷,后面用到时得记着。
四、三个口径坑
坑一:年度批次不等于存量
这是最容易出错的一处。我统计的是 2025 这一年公示出来的批次,广东 3,758 条;而广东省工信厅 2026 年 9 月的政策解读口径是「累计培育专精特新中小企业超 3 万家」。
两个数字都对,回答的问题不同:一个是当年新增认定,一个是累计培育。写分析时如果把两者混着用,或者直接拿其中一个否定另一个,结论就站不住。
我最后的处理是:所有对外输出都明确标注「2025 年度公示批次」,并在提到存量时单独注明来源与时间。
坑二:地区字段来自公示文件,不是工商注册地
深圳单列公示。如果只按省厅文件计数,广东会少掉最大的一块——深圳 2,535 条,占广东的六成以上。
我按公示文件的归属合并,广东合计 3,758 条(含深圳 2,535)。这个口径下「地区」字段表示的是「谁发布的」,不完全等于企业注册地。
坑三:城市字段是推断出来的
公示文本通常只有企业名称和批次,没有注册地。城市只能从企业名称里的地名推断:
CITY_HINTS = ["上海", "深圳", "苏州", "南京", "无锡", "常州",
"东莞", "合肥", "芜湖", "佛山"]
def guess_city(name: str):
for city in CITY_HINTS:
if city in name:
return city
return None
结果:22,960 条里有 6,385 条推断不出,留空。占四分之一还多。
这个比例意味着城市分布只能看趋势,不能当注册地口径用。我在输出时保留了「城市分布仅作趋势参考」的标注——推断字段和原始字段必须区分开,否则后面的所有分析都建立在沙子上面。
五、抓完之后,这份数据能用来做什么
先说不能做什么。
公示文本里能稳定拿到的字段只有两个:企业名称、所属批次,部分文件带地市。没有官网地址、没有主营产品、没有联系人、没有技术方向、没有统一社会信用代码。
所以它能证明的只有一件事:这家公司存在,且在某年被认定为省级专精特新。
它能用来做的是核验:拿一份企业名单跟它比对,确认哪些企业在名单里、是哪一批。这个用途很具体,也够用。
它做不到的是描述能力。想知道这家企业做什么、能做到什么精度、交期多久、给谁供过货,公示文件上一个字都没有——这些得去别处找,或者由企业自己写出来。
六、一句小结
抓数据之前先想清楚字段集。22,960 条听起来不小,但每条只有两个可用字段,它能支撑的结论就那么多。
我见过不少分析把「名单上有多少家企业」直接当成「这个行业有多少能干的玩家」来用,中间差的那一步就是字段集的限制。数据量大不等于信息量大,这两件事在数据抓取这个行当里经常被搞混。
下一轮我打算换个方向:拿固定问题集去问一批 AI 平台,看答案里出现的名字和这份名单的重合度有多高。那组数据得等跑完再写。