我花了14个小时找了一下长春长生们究竟卖到了哪里去

640?wx_fmt=gif

640?wx_fmt=jpeg


640?wx_fmt=png

前言


全文的观点从技术讨论出发,尽量客观中立,观点及行为为员工自发,不代表本人所在公司及团队。

需要说明的是这次数据是涵盖所有的疫苗数据,并不是针对此次问题疫苗定向搜集的数据,所有数据皆来自于政府相关网站的公开数据。


640?wx_fmt=png

数据采集源


因为有一些数据实在太难找了,只能来看一下近两年的数据,并且不考虑疫苗增补名单数据(太零碎了)。

所以这次整理的数据并不完善,所以把所有搜集到的数据全部同步到了GitHub(https://github.com/fuckcqcs/fuckcqcs),有需要可以自取或者提issue和pr。

因为时间跨度较大,所以没有把批次的信息纳入本次的统计范围。本文主要从技术层面搜集了此次问题疫苗事件相关企业生产的各类疫苗在各省份的销售情况。

采集关键词

  • 省名  第二类疫苗  采购

  • 省名  第二类疫苗  公示

  • 省名  第二类疫苗  产品及价格

  • 省名  第二类疫苗  供应商

  • 省名  第二类疫苗  中标目录

  • 省名  第二类疫苗  参考价

  • 省名  第二类疫苗  入围结果

采集结果整理如下

  • 北京市,来源:北京市2018-2019年免疫规划用第二类疫苗采购项目

  • 天津市,来源天津市2018-2020年第二类疫苗集中采购项目拟中标/拟中选结果

  • 上海市,来源2018 年度上海市第二类疫苗集团采购项目中标目录

  • 重庆市,来源重庆市第二类疫苗供应商入围采购-采购结果预公示

  • 河北省,来源河北省疾病预防控制中心2018年度第二类疫苗省级集中采购项目中标公告

  • 山西省,来源2018年度山西省第二类疫苗集中采购入围企业产品及价格

  • 辽宁省,来源辽宁省第二类疫苗平台招标采购公告

  • 吉林省,来源2017年度吉林省第二类疫苗集中采购企业产品议价结果名单

  • 黑龙江省,来源黑龙江省2018年第二类疫苗挂网采购中标企业产品及价格审核结果

  • 江苏省,来源江苏省第二类疫苗集中采购中标产品

  • 浙江省,来源浙江省2018年第二类疫苗中标目录

  • 安徽省,来源安徽省2018年第二类疫苗集中采购目录

  • 福建省,来源福建省2018年第二类疫苗集中采购目录_湄洲岛

  • 江西省,来源1228江西省2018年度第二类疫苗入围品种目录

  • 山东省,「找不到」

  • 河南省,来源2017年河南省二类疫苗供应商入围资格采购项目中标结果公告

  • 湖北省,来源2017年湖北省第二类疫苗集中采购成交产品

  • 湖南省,来源湖南省第二类疫苗集中采购文件

  • 广东省,来源2018年度广东省第二类疫苗成交品种目录

  • 海南省,来源海南省第二类疫苗品种目录(第一批)

  • 四川省,来源2017年度第二类疫苗挂网阳光采购结果

  • 贵州省,来源贵州省第二类疫苗集中采购报价解密结果

  • 云南省,来源云南省疾病预防控制中心二类疫苗公开招标入围项目入围公告

  • 陕西省,来源陕西省2018年二类疫苗集中采购项目入围供应商磋商结果

  • 甘肃省,来源甘肃省第二类疫苗供应资格采购项目中标公示

  • 青海省,来源所有的第二类的价格信息全部转到223.220.250.135:8038  无法查看

  • 台湾省,暂无

  • 内蒙古自治区,2018年内蒙古自治区第二类疫苗集中采购入围企业产品及价格

  • 广西壮族自治区,2017年度广西壮族自治区第二类疫苗直接挂网采购拟入围产品目录(电子版)

  • 西藏自治区,实在找不到

  • 宁夏回族自治区,2016年宁夏回族自治区第二类疫苗公开招标预中标结果

  • 新疆维吾尔自治区,《自治区2017年第二类疫苗入围品种及价格目录》20170828.xls

  • 香港特别行政区,暂无

  • 澳门特别行政区,暂无

综上,除去港澳台 ,山东,青海以及西藏以外,只搜集到了28个省级行政区的二类疫苗数据公示情况。

单单是检索,下载的过程,就花了7个多小时,主要遇到了一些问题:

  • 某些网站需要注册登录才可以查看;

  • 有些网站缺乏维护被挂了黑链;

  • 搜索框有,但是实际并不能搜索;

  • 有些只有图片,没有文字;

  • 有些只在纯公告但无具体数据;

  • 找不到信息的有:

  • 山东省,只看到新闻说建了可追溯的展示平台,但本次暂未找到;

  • 青海省,所有的第二类的价格信息需要账号登录进相关系统才能访问;

  • 西藏,暂时没能搜索到相关数据。

如图,最终获取到28个省份的数据(图中漏掉了河北)。

640?wx_fmt=png640?wx_fmt=png

数据整理


由于本人不是专业的医学行业人士,所以统一把数据整理成以下的csv格式。

通用名,来源,生产企业,申报企业,省,中标年份

name,src,create_company,report_company,prov,year

各项含义如下:

  • 通用名 :药名  -> name

  • 来源:国产/进口 -> src

  • 生产企业 ->  create_company

  • 申报企业:如果为空再填充为生产企业 ->  report_company

  • 省  ->  prov

  • 中标年份 ->  year

期间因为整理非XLS的文件消耗了大量的时间,暂时只能先把成型的数据集提取出来。

640?wx_fmt=png

目前处理结果如下:

  • 数据标准csv(14)

  • 吉林省,四川省,天津市,宁夏回族自治区,安徽省,山西省,广东省,新疆维吾尔自治区,江苏省,江西省,海南省,贵州省,辽宁省,黑龙江省

  • 等待整理的数据(13)

  • 上海市,云南省,内蒙古,北京市,广西省,河南省,浙江省,湖北省,湖南省,甘肃省,福建省,重庆市,陕西省

如图所示:

640?wx_fmt=jpeg

亮绿色是容易获取的数据;暗绿色的可以获取的数据;黑色的是没有获取到数据。


640?wx_fmt=png

数据分析


直接采用Pandas+Echart进行处理。首先把所有的csv整合,共有1529条数据,对所有的生成企业进行统计分析:

count    167.000000
mean       9.143713
std       15.839281
min        1.000000
25%        1.000000
50%        3.000000
75%        9.000000
max       98.000000

共 167 个厂家,其中中位数是3,最高是98,很明显这是一个偏态分布。顺手看一下箱线图:

640?wx_fmt=png

也就是说,绝大多数的药,都由大厂生产。我们输出前10个看看,长春长生位列第2。

生产厂家数量
北京科兴生物制品有限公司98
长春长生生物科技有限责任公司91
华兰生物疫苗有限公司72
玉溪沃森生物技术有限公司57
上海生物制品研究所有限责任公司56
大连雅立峰生物制药有限公司51
长春生物制品研究所有限责任公司50
华北制药金坦生物技术股份有限公司46
辽宁成大生物股份有限公司44
北京智飞绿竹生物制药有限公司43

我们再来看看各个省份中,长春长生等占据的百分比:

[{'name''天津''value': 14.0625},
 {'name''辽宁''value': 17.647058823529413},
 {'name''黑龙江''value': 13.274336283185843},
 {'name''安徽''value': 9.75609756097561},
 {'name''新疆''value': 16.94915254237288},
 {'name''江苏''value': 14.563106796116504},
 {'name''江西''value': 12.179487179487179},
 {'name''山西''value': 16.52173913043478},
 {'name''吉林''value': 17.857142857142858},
 {'name''贵州''value': 14.17910447761194},
 {'name''广东''value': 13.445378151260504},
 {'name''四川''value': 16.93548387096774},
 {'name''宁夏''value': 17.5},
 {'name''海南''value': 14.285714285714285}]

长春长生等在14个有数据的省份供应商中均占有一席之地:

640?wx_fmt=png

亮红色接近20%;暗红色接近10%;黑色的是没有获取到数据。

对比下从官网下载的公司销售策略图:

640?wx_fmt=png

做到这里已经花了整整14小时,才将将整理了一半的省份。所以目前的数据并不完整,仅供参考,后面空了可能会继续整理更新到Github(https://github.com/fuckcqcs/fuckcqcs)上。


640?wx_fmt=png

后记


除了在朋友圈和微博刷屏表达我们的愤怒,或许我们还能做点什么,这也是我的出发点。最初的文章里面有些措辞不是太中性,抱歉,本只想在自己能力范围内做一点事情。

如果说有什么建议的话,希望相关部门在数据公示方面后续能继续加强吧。

声明:本文经授权转自同程安全应急响应中心,版权归对方所有。


征稿啦

优快云 公众号秉持着「与千万技术人共成长」理念,不仅以「极客头条」、「畅言」栏目在第一时间以技术人的独特视角描述技术人关心的行业焦点事件,更有「技术头条」专栏,深度解读行业内的热门技术与场景应用,让所有的开发者紧跟技术潮流,保持警醒的技术嗅觉,对行业趋势、技术有更为全面的认知。

如果你有优质的文章,或是行业热点事件、技术趋势的真知灼见,或是深度的应用实践、场景方案等的新见解,欢迎联系 优快云 投稿,联系方式:微信(guorui_1118,请备注投稿+姓名+公司职位),邮箱(guorui@youkuaiyun.com)。


————— 推荐阅读 —————


640?wx_fmt=png

640?wx_fmt=png

640?wx_fmt=png

640?wx_fmt=gif640?wx_fmt=gif

<think>好的,我现在需要解决用户的问题:如何用C语言根据给定的源IP生成同一网段内的新IP地址。首先,我得理清楚相关知识点,确保自己理解正确,然后再思考如何实现。 首先,用户提到了IP地址的结构。根据引用[1],IPv4地址是32位的,分为网络部分和主机部分。要生成同一网段的IP,必须保证网络部分相同,主机部分不同。但问题在于,如何确定网络部分的长度,也就是子网掩码的问题。用户提供的引用中没有直接提到子网掩码,但这是关键点,因为子网掩码决定了哪些位是网络部分,哪些是主机部分。 接下来,用户想用C语言实现。我需要考虑如何解析源IP和子网掩码,然后生成新的主机部分。例如,如果子网掩码是255.255.255.0,那么前24位是网络,后8位是主机。生成新IP时,保持网络部分不变,随机或按某种规则修改主机部分。 步骤可能包括: 1. 将源IP和子网掩码转换为32位整数。 2. 对这两个整数进行按位与运算,得到网络地址。 3. 生成一个随机的主机地址,确保不为0或全1(避免网络地址和广播地址)。 4. 将网络地址和新的主机地址组合,得到新IP。 但用户的问题中没有提到子网掩码,可能需要用户提供,或者假设标准的子网掩码(如C类默认是24位)。但更正确的方法应该是根据实际的子网掩码来计算,所以程序可能需要用户输入子网掩码,或者通过其他方式获取。 然后,具体到C语言的实现,需要考虑IP地址的解析,比如将点分十进制的字符串转换为四个字节,处理成32位整数。然后进行位操作,生成新的主机部分,再转换回点分十进制格式。 可能的难点在于处理不同的子网掩码,例如非连续的掩码,但通常情况下子网掩码是连续的,所以可以计算网络位数。例如,子网掩码255.255.255.0对应24位网络前缀。 例如,如果源IP是192.168.1.100,子网掩码是255.255.255.0,网络部分是前24位,主机部分是后8位。生成新IP时,保持前24位不变,后8位随机生成(但排除0和255)。 但如何获取子网掩码呢?用户的问题中没有说明,可能需要作为输入参数,或者假设使用默认的子网掩码,但这可能不准确。例如,B类私有地址的默认掩码是16位,但根据引用[5],B类私有地址的子网划分可能更复杂。因此,正确的做法应该是让用户提供子网掩码,或者根据IP地址的类型(A/B/C类)推断默认掩码,但这可能不够灵活。 因此,在代码中,可能需要用户输入源IP和子网掩码,然后进行处理。或者,如果无法获取子网掩码,可能需要其他方法,但这可能不可靠。 假设用户会提供子网掩码,接下来在C语言中如何处理? 步骤分解: 1. 解析源IP和子网掩码为四个字节的结构。 例如,将“192.168.1.100”转换为四个unsigned char的数组:192, 168, 1, 100。 同样处理子网掩码,如“255.255.255.0”转换为255, 255, 255, 0。 2. 将源IP和子网掩码转换为32位无符号整数。 例如,ip_num = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4; mask_num同理。 3. 计算网络地址:network = ip_num & mask_num; 4. 计算主机部分的位数。例如,子网掩码的二进制中0的位数即为主机位数。可以通过计算mask_num的反码中末尾的1的个数。例如,mask为255.255.255.0(即0xFFFFFF00),其反码是0x000000FF,二进制中后面8位是1,所以主机位数是8。 5. 生成一个随机的主机号,范围是1到(2^host_bits - 2),避免全0和全1。 6. 将主机号与网络地址进行按位或运算,得到新的IP地址。 7. 将新的IP地址转换为点分十进制字符串。 现在需要考虑如何实现这些步骤,特别是如何计算主机位数和生成随机主机号。 可能的代码结构: 函数1:将点分十进制字符串转换为32位整数。 函数2:将32位整数转换为点分十进制字符串。 函数3:计算主机位数,通过mask的二进制形式中0的位数,或者计算反码的连续1的位数。 例如,对于mask_num,取反得到host_mask,然后计算host_mask中最低位开始的连续1的位数。或者,用位运算到主机位数。 例如,对于host_mask = ~mask_num,然后计算最右边的连续1的位数。例如,如果host_mask是0x000000FF(即255),则二进制是00000000 00000000 00000000 11111111,所以主机位数是8。 计算这个的方法可以是到第一个1的位置,然后计算后面有多少位连续的1。或者,更简单的方法是计算host_mask + 1是否为2的幂,然后取对数。例如,host_mask +1是0x100,即256,是2^8,所以主机位数是8位。 但需要处理特殊情况,比如host_mask为0的情况(此时掩码是255.255.255.255,主机位数为0,无法生成新IP)。 另外,生成随机数时,要确保在有效范围内。例如,主机位数是h_bits,则最大主机号是 (1 << h_bits) -1 -1 = 2^h_bits -2。例如,h_bits=8,则最大是254。 然后,随机数生成的范围是1到254。 如果主机位数是0,或者无法生成有效的主机号,则需要处理错误。 综上,代码的大致流程: 解析源IP和子网掩码为整数。 计算网络地址。 计算主机位数。 如果主机位数为0,报错。 生成随机主机号。 组合网络地址和主机号得到新IP。 转换为字符串。 现在,具体到C语言代码,需要考虑如何解析字符串,处理位操作,生成随机数。 可能的代码: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> // 将点分十进制IP转换为32位整数 unsigned int ip_to_int(const char *ip) { unsigned int a, b, c, d; sscanf(ip, "%u.%u.%u.%u", &a, &b, &c, &d); return (a << 24) | (b << 16) | (c << 8) | d; } // 将32位整数转换为点分十进制IP void int_to_ip(unsigned int num, char *buffer) { unsigned char bytes[4]; bytes[0] = (num >> 24) & 0xFF; bytes[1] = (num >> 16) & 0xFF; bytes[2] = (num >> 8) & 0xFF; bytes[3] = num & 0xFF; sprintf(buffer, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]); } // 计算主机位数 int calculate_host_bits(unsigned int mask) { unsigned int host_mask = ~mask; if (host_mask == 0) { return 0; // 无主机位 } host_mask++; // 例如,0xFF -> 0x100,是2^8 int bits = 0; while (host_mask > 1) { host_mask >>= 1; bits++; } return bits; } int main() { srand(time(NULL)); const char *src_ip = "192.168.1.100"; const char *mask = "255.255.255.0"; unsigned int src = ip_to_int(src_ip); unsigned int mask_num = ip_to_int(mask); unsigned int network = src & mask_num; int host_bits = calculate_host_bits(mask_num); if (host_bits <= 0) { printf("No available host bits.\n"); return 1; } unsigned int max_host = (1u << host_bits) - 2; // 最大值是2^host_bits -2 unsigned int host = (rand() % max_host) + 1; // 生成1到max_host的随机数 unsigned int new_ip = network | host; char new_ip_str[16]; int_to_ip(new_ip, new_ip_str); printf("New IP: %s\n", new_ip_str); return 0; } 但这里有个问题:host的计算是否正确?例如,当mask是255.255.255.0时,主机位数是8,max_host是254。host变量应该是0到255之间的值,但需要确保它只在主机部分,并且不与网络部分冲突。例如,网络部分是前24位,主机部分是后8位。所以,当network是192.168.1.0,host是100的话,新IP是192.168.1.100。但上面的代码中,network是src & mask_num,比如src是192.168.1.100,mask_num是255.255.255.0,那么network是192.168.1.0。然后,host是随机生成的1到254之间的数,那么new_ip就是192.168.1.0 | host,例如host=100的话就是192.168.1.100,是正确的。 但代码中的host是直接作为最后的位,所以假设host部分在低host_bits位。但这里是否有可能host的高位覆盖网络部分?例如,如果mask不是连续的,比如255.255.0.255,这时候主机位数可能不在最后几位,此时这种方法就不正确了。但通常子网掩码是连续的,所以可能不需要考虑这种情况。如果用户需要处理非连续掩码,问题会更复杂,但大多数情况下,子网掩码是连续的,所以这段代码可以工作。 另一个需要注意的地方是,在计算host时,应该只填充主机部分的位。例如,当host_bits是8位时,host变量应该在0到255之间,但是要排除0和255。所以生成的是1到254之间的随机数。但代码中的max_host是 (1u << host_bits) -2,例如8位的话是256-2=254,所以rand()%max_host得到0到253,然后+1变成1到254,这样是正确的。 综上,这个代码应该可以生成同一网段内的新IP地址。但需要用户输入正确的子网掩码。如果用户不知道子网掩码,可能需要其他方法,比如根据IP地址的类别(A/B/C类)推断默认掩码,但这可能不准确,尤其是在CIDR(无类域间路由)广泛使用的今天。因此,正确的做法是要求用户提供子网掩码。 可能的测试案例:源IP是192.168.1.100,子网掩码255.255.255.0,生成的新IP应该在192.168.1.1到192.168.1.254之间。 此外,还需要处理可能的错误情况,比如子网掩码无效,或者主机位数为0的情况。 因此,最终的代码需要包含这些步骤,并确保正确性。</think>### 根据源IP生成同一网段IP的方法 要生成与源IP同一网段的新IP地址,需通过子网掩码确定网络标识和主机标识。步骤如下: 1. **解析源IP和子网掩码** 将点分十进制格式的IP地址转换为32位整数,例如$192.168.1.100$转换为`0xC0A80164`。 2. **计算网络地址** 网络地址 = 源IP & 子网掩码。例如: $$192.168.1.100 \ \& \ 255.255.255.0 = 192.168.1.0$$ 3. **确定主机位数** 子网掩码的反码(如$0.0.0.255$)中连续1的位数即为主机位数。例如,掩码$255.255.255.0$对应主机位数为8。 4. **生成随机主机号** 主机号范围需避开全0(网络地址)和全1(广播地址)。例如,8位主机号的有效范围是$1$到$254$。 5. **组合新IP** 新IP = 网络地址 | 随机主机号。 ### C语言实现代码 ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> // 将IP字符串转为32位整数 unsigned int ip_to_int(const char *ip) { unsigned int a, b, c, d; sscanf(ip, "%u.%u.%u.%u", &a, &b, &c, &d); return (a << 24) | (b << 16) | (c << 8) | d; } // 将32位整数转为IP字符串 void int_to_ip(unsigned int num, char *buffer) { unsigned char bytes[4]; bytes[0] = (num >> 24) & 0xFF; bytes[1] = (num >> 16) & 0xFF; bytes[2] = (num >> 8) & 0xFF; bytes[3] = num & 0xFF; sprintf(buffer, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]); } // 计算主机位数(需连续子网掩码) int calculate_host_bits(unsigned int mask) { unsigned int host_mask = ~mask; if (host_mask == 0) return 0; host_mask++; // 例如:0xFF → 0x100,表示8位主机 int bits = 0; while (host_mask > 1) { host_mask >>= 1; bits++; } return bits; } int main() { srand(time(NULL)); // 输入源IP和子网掩码 const char *src_ip = "192.168.1.100"; const char *subnet_mask = "255.255.255.0"; unsigned int src = ip_to_int(src_ip); unsigned int mask = ip_to_int(subnet_mask); unsigned int network = src & mask; // 计算可用主机位数 int host_bits = calculate_host_bits(mask); if (host_bits <= 0) { printf("错误:无效的子网掩码\n"); return 1; } // 生成随机主机号(1 ≤ host ≤ 2^host_bits -2) unsigned int max_host = (1u << host_bits) - 2; unsigned int host = (rand() % max_host) + 1; // 组合新IP unsigned int new_ip = network | host; char new_ip_str[16]; int_to_ip(new_ip, new_ip_str); printf("源IP: %s\n新IP: %s\n", src_ip, new_ip_str); return 0; } ``` ### 关键说明 - **子网掩码的作用**:明确网络标识和主机标识的分界[^1]。 - **主机号范围**:需跳过全0(网络地址)和全1(广播地址)[^5]。 - **局限性**:假设子网掩码是连续的(如$255.255.255.0$),非连续掩码需更复杂处理。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值