Java爬虫-爬取疫苗批次信息

打印 上一主题 下一主题

主题 914|帖子 914|积分 2742

        本年3月份开始,就接到通知, 根据《关于开展有关人群第二剂次脊髓灰质炎灭活疫苗补种工作的通知》国疾控卫免发〔2024〕1号文件要求,在2016年3月1日至2019年9月30日之间出生的儿童,凡无接种禁忌者,需补齐2剂次脊髓灰质炎灭活疫苗。由于我家一直是异地注射【在外漂打工,懂的都懂】,疫苗本上信息又特别有限【吐槽-六七年前的疫苗本缺陷太大了:无厂家,无备注是否口服,无备注是灭活还是减毒】,上周去注射被问及6年前的第一针是注射还是口服,瞬间被问住了,记得3年前幼儿园入学前的注射就已经被工作人员问过一次了,问脊髓灰质炎疫苗第二、三针是注射还是口服的,甲肝疫苗是活疫苗还是灭活疫苗。。。

 
        颠末网上各种搜索,通过疫苗本上写的批号到网上查询追溯,最后发现在【中国食品药品检定研究院】https://bio.nifdc.org.cn/pqf/search.do?formAction=pqfQkcx上可以查询,但是这个查询也太难用了,该网站需要厂家+疫苗名+批号三个条件查询,但我只知道批号,其它信息一概不知。。。
作为技术人员,一怒之下,写了个爬虫,把该网站近十年公布的疫苗批次信息全都抓到本地。。。
上菜:
  1. <dependency>
  2.    <groupId>cn.hutool</groupId>
  3.    <artifactId>hutool-http</artifactId>
  4.    <version>5.8.23</version>
  5. </dependency>
  6. <dependency>
  7.    <groupId>org.jsoup</groupId>
  8.    <artifactId>jsoup</artifactId>
  9.    <version>1.17.2</version>
  10. </dependency>
  11. <dependency>
  12.    <groupId>org.springframework.boot</groupId>
  13.    <artifactId>spring-boot-starter-data-mongodb</artifactId>
  14. </dependency>
复制代码
 
  1. /**
  2. * 获取疫苗批次
  3. * @author zhaokk
  4. * @since 2024/5/26
  5. */
  6. public class GetVaccinBatch {
  7.     public static String BASE_URL = "https://bio.nifdc.org.cn/pqf/";
  8.     public static void main(String[] args) throws IOException {
  9.         String[] listUrlArray = {
  10.                 //中国食品药品检定研究院
  11.                 "search.do?formAction=pqfGsByJG&parameter1=1",
  12.                 //北京市药品检验研究院
  13.                 "search.do?formAction=pqfGsByJG&parameter1=5b6ea8c91cf9013d011cfdfbda100041",
  14.                 //上海市食品药品检验研究院
  15.                 "search.do?formAction=pqfGsByJG&parameter1=4028813a1d225be5011d2265474b0004",
  16.                 //广东省药品检验所
  17.                 "search.do?formAction=pqfGsByJG&parameter1=4028813a1d225be5011d226a9159001c",
  18.                 //四川省药品检验研究院(四川省医疗器械检测中心)
  19.                 "search.do?formAction=pqfGsByJG&parameter1=4028813a1d225be5011d226ba310001e",
  20.                 //湖北省药品监督检验研究院
  21.                 "search.do?formAction=pqfGsByJG&parameter1=4028813a1d225be5011d22697942001a",
  22.                 //吉林省药品检验研究院
  23.                 "search.do?formAction=pqfGsByJG&parameter1=4028813a1d225be5011d226392100002",
  24.                 //甘肃省药品检验研究院
  25.                 "search.do?formAction=pqfGsByJG&parameter1=4028813a1d225be5011d226c637d0020",
  26.                 //重庆市食品药品检验检测研究院
  27.                 "search.do?formAction=pqfGsByJG&parameter1=20190917c001",
  28.                 //山东省食品药品检验研究院
  29.                 "search.do?formAction=pqfGsByJG&parameter1=20190924c001",
  30.                 //辽宁省药品检验检测院
  31.                 "search.do?formAction=pqfGsByJG&parameter1=20210315c001",
  32.                 //云南省食品药品监督检验研究院
  33.                 "search.do?formAction=pqfGsByJG&parameter1=20210926c001",
  34.                 //河北省药品医疗器械检验研究院
  35.                 "search.do?formAction=pqfGsByJG&parameter1=20211011c001",
  36.                 //浙江省食品药品检验研究院
  37.                 "search.do?formAction=pqfGsByJG&parameter1=20210210c002"
  38.         };
  39.         MongoDbUtils.connect("mongodb://127.0.0.1:27017", "vaccin-batch");
  40.         for (String listUrl : listUrlArray) {
  41.             //发送http请求
  42.             Document document = Jsoup.connect(BASE_URL+listUrl).get();
  43.             Elements aList = document.select("table tr td > a");
  44.             for (int i = aList.size()-1; i >= 0; i--) {
  45.                 Element a = aList.get(i);
  46.                 String atext = a.text();
  47.                 String ahref = a.attr("href");
  48.                 String publishDateStr = atext.substring(atext.length()-11, atext.length()-1);
  49.                 System.out.println(atext + ":" + ahref);
  50.                 System.out.println("公布日期:" + publishDateStr);
  51.                 org.bson.Document saveLogDoc = new org.bson.Document();
  52.                 saveLogDoc.append("notice_list_url", BASE_URL+listUrl);
  53.                 saveLogDoc.append("notice_detail_url", BASE_URL+ahref);
  54.                 saveLogDoc.append("notice_title", atext);
  55.                 List<org.bson.Document> saveLogList = MongoDbUtils.findBy("vaccin-batch-savelog", saveLogDoc);
  56.                 if(!saveLogList.isEmpty()){
  57.                     System.out.println(BASE_URL+ahref + "【"+ atext + "】已存在,跳过");
  58.                     continue;
  59.                 }
  60.                 viewDetail(BASE_URL+ahref, atext);
  61.                 saveLogDoc.append("publish_date", publishDateStr);
  62.                 saveLogDoc.append("create_time", DateUtil.now());
  63.                 MongoDbUtils.insert("vaccin-batch-savelog", saveLogDoc);
  64.             }
  65.         }
  66.     }
  67.     public static void viewDetail(String noticeDetailUrl, String noticeTitle) throws IOException {
  68. //        Document document = Jsoup.connect(noticeDetailUrl).get();
  69.         Connection.Response resp = Jsoup.connect(noticeDetailUrl)
  70.                 .timeout(60000)
  71.                 .method(Connection.Method.GET)
  72.                 .maxBodySize(0)
  73.                 .followRedirects(false)
  74.                 .execute();
  75.         String htmlStr = new String(resp.bodyAsBytes());
  76.         Document document = Jsoup.parse(htmlStr);
  77.         Elements theadList = document.select("table thead tr");
  78.         if(theadList.isEmpty() || theadList.size() != 2){
  79.             throw new RuntimeException("未解析到信息");
  80.         }
  81.         Elements theadCols = theadList.get(1).select("td");
  82.         Elements tbodyList = document.select("table thead + tbody tr");
  83.         if(tbodyList.isEmpty()){
  84.             throw new RuntimeException("未解析到信息");
  85.         }
  86.         for (Element row : tbodyList) {
  87.             Elements cols = row.select("td");
  88.             if(cols.size() != theadCols.size()){
  89. //                break;
  90.                 System.out.println(document);
  91.                 System.out.println(noticeDetailUrl);
  92.                 System.out.println(row);
  93.                 throw new RuntimeException("未解析到正确的信息");
  94.             }
  95.             org.bson.Document mongoDoc = new org.bson.Document();
  96.             for (int i = 0; i < cols.size(); i++) {
  97.                 String key = FieldEnum.getName(theadCols.get(i).text());
  98.                 if(StrUtil.isBlank(key)){
  99.                     continue;
  100.                 }
  101.                 mongoDoc.append(key, cols.get(i).text());
  102.             }
  103.             mongoDoc.append("notice_title", noticeTitle);
  104.             mongoDoc.append("notice_detail_url", noticeDetailUrl);
  105.             //保存数据库
  106.             MongoDbUtils.insert("vaccin-batch", mongoDoc);
  107.         }
  108.     }
  109. }
  110. /**
  111. * @author zhaokk
  112. * @since 2024/5/26
  113. */
  114. public enum FieldEnum {
  115.     PRODUCT_NAME("产品名称", "product_name"),
  116.     SPEC("规格", "spec"),
  117.     BATCH_NO("批号", "batch_no"),
  118.     QUANTITY("签发量", "quantity"),
  119.     VALID_DATE("有效期至", "valid_date"),
  120.     PRODUCER("生产企业", "producer"),
  121.     PRODUCER_ORG("上市许可持有人", "producer"),
  122.     CHECK_NO("收检编号", "check_no"),
  123.     CERT_NO("证书编号", "cert_no"),
  124.     REPORT_NO("报告编号", "report_no"),
  125.     SIGN_DATE("签发日期", "sign_date"),
  126.     SIGN_REMARK("签发结论", "sign_remark"),
  127.     SIGN_ORG("批签发机构", "sign_org")
  128.     ;
  129.     private String remark;
  130.     private String name;
  131.     FieldEnum(String remark, String name) {
  132.         this.remark = remark;
  133.         this.name = name;
  134.     }
  135.     public static String getName(String remark){
  136.         for(FieldEnum value : FieldEnum.values()){
  137.             if(remark.equals(value.getRemark())){
  138.                 return value.getName();
  139.             }
  140.         }
  141.         return null;
  142.     }
  143.     public String getRemark() {
  144.         return remark;
  145.     }
  146.     public void setRemark(String remark) {
  147.         this.remark = remark;
  148.     }
  149.     public String getName() {
  150.         return name;
  151.     }
  152.     public void setName(String name) {
  153.         this.name = name;
  154.     }
  155. }
复制代码
再搭配一道菜mogodb Util,不用跑什么tomcat,运行main函数直接就是开干,最后通过Navicat等工具连上随意检索。

 
  1. import com.mongodb.BasicDBObject;
  2. import com.mongodb.MongoWriteException;
  3. import com.mongodb.client.*;
  4. import com.mongodb.client.model.Filters;
  5. import com.mongodb.client.result.DeleteResult;
  6. import com.mongodb.client.result.UpdateResult;
  7. import org.bson.Document;
  8. import org.bson.conversions.Bson;
  9. import org.bson.types.ObjectId;
  10. import java.util.ArrayList;
  11. import java.util.List;
  12. /**
  13. * MongoDb 操作类
  14. * @author zhaokui
  15. * 2018年1月31日
  16. */
  17. public class MongoDbUtils {
  18.    
  19.    private static MongoDatabase db;
  20.     /**
  21.      * 链接数据库
  22.      *            
  23.      * @param uri
  24.      *            主机名 + 端口号
  25.      * @param databaseName
  26.      *            数据库名称
  27.      *            
  28.      */
  29.     public static void connect(String uri, String databaseName) {
  30.         MongoClient client = MongoClients.create(uri);
  31.         db = client.getDatabase(databaseName);  
  32.     }
  33.    
  34.     public static MongoCollection<Document> getCollection(String collectionName){
  35.        return db.getCollection(collectionName);
  36.     }
  37.    
  38.    
  39.     /**
  40.      * 插入一个文档
  41.      *  
  42.      * @param document
  43.      *            文档
  44.      */  
  45.     public static void insert(String collectionName, Document document) {  
  46.        getCollection(collectionName).insertOne(document);  
  47.     }
  48.     /**
  49.      * 插入一个文档
  50.      *  
  51.      * @param document
  52.      *            文档
  53.      */  
  54.     public static void insertv2(String collectionName, Document document) throws Exception {  
  55.           try{
  56.              getCollection(collectionName).insertOne(document);
  57.           }catch(MongoWriteException e) {
  58.              e.printStackTrace();
  59.           }
  60.     }  
  61.    
  62.     /**
  63.      * 查找对象 - 根据主键_id
  64.      *
  65.      * @param collectionName
  66.      * @param id
  67.      * @return
  68.      */
  69.     public static Document findById(String collectionName, String id) {
  70.         ObjectId _idobj = null;
  71.         try {
  72.             _idobj = new ObjectId(id);
  73.         } catch (Exception e) {
  74.             return null;
  75.         }
  76.         Document myDoc = getCollection(collectionName).find(Filters.eq("_id", _idobj)).first();
  77.         return myDoc;
  78.     }
  79.   
  80.     /**
  81.      * 查询所有文档
  82.      *  
  83.      * @return 所有文档集合
  84.      */  
  85.     public static List<Document> findAll(String collectionName) {  
  86.         List<Document> results = new ArrayList<Document>();  
  87.         FindIterable<Document> iterables = getCollection(collectionName).find();  
  88.         MongoCursor<Document> cursor = iterables.iterator();  
  89.         while (cursor.hasNext()) {  
  90.             results.add(cursor.next());  
  91.         }  
  92.   
  93.         return results;  
  94.     }  
  95.   
  96.     /**
  97.      * 查询所有文档
  98.      *  
  99.      * @return 所有文档集合
  100.      */  
  101.     public static List<Document> findAll(String collectionName, Bson orderBy) {  
  102.         List<Document> results = new ArrayList<Document>();  
  103.         FindIterable<Document> iterables = getCollection(collectionName).find().sort(orderBy);  
  104.         MongoCursor<Document> cursor = iterables.iterator();  
  105.         while (cursor.hasNext()) {  
  106.             results.add(cursor.next());  
  107.         }  
  108.   
  109.         return results;  
  110.     }
  111.    
  112.     /**
  113.      * 根据条件查询
  114.      *  
  115.      * @param filter
  116.      *            查询条件 //注意Bson的几个实现类,BasicDBObject, BsonDocument,
  117.      *            BsonDocumentWrapper, CommandResult, Document, RawBsonDocument
  118.      * @return 返回集合列表
  119.      */  
  120.     public static List<Document> findBy(String collectionName, Bson filter) {  
  121.         List<Document> results = new ArrayList<Document>();  
  122.         FindIterable<Document> iterables = getCollection(collectionName).find(filter);
  123.         MongoCursor<Document> cursor = iterables.iterator();  
  124.         while (cursor.hasNext()) {  
  125.             results.add(cursor.next());  
  126.         }  
  127.   
  128.         return results;  
  129.     }  
  130.    
  131.     /**
  132.      * 根据条件查询 + 排序
  133.      *  
  134.      * @param filter
  135.      *            查询条件 //注意Bson的几个实现类,BasicDBObject, BsonDocument,
  136.      *            BsonDocumentWrapper, CommandResult, Document, RawBsonDocument
  137.      * @return 返回集合列表
  138.      */  
  139.     public static List<Document> findBy(String collectionName, Bson filter, Bson orderBy) {  
  140.         List<Document> results = new ArrayList<Document>();  
  141.         FindIterable<Document> iterables = getCollection(collectionName).find(filter).sort(orderBy);  
  142.         MongoCursor<Document> cursor = iterables.iterator();  
  143.         while (cursor.hasNext()) {  
  144.             results.add(cursor.next());  
  145.         }  
  146.   
  147.         return results;  
  148.     }  
  149.    
  150.     public static List<Document> findBy(String collectionName, Bson filter, Bson orderBy, int pageSize) {  
  151.         List<Document> results = new ArrayList<Document>();  
  152.         FindIterable<Document> iterables = getCollection(collectionName).find(filter).sort(orderBy).limit(pageSize);  
  153.         MongoCursor<Document> cursor = iterables.iterator();  
  154.         while (cursor.hasNext()) {  
  155.             results.add(cursor.next());  
  156.         }  
  157.         return results;  
  158.     }  
  159.    
  160.     /** 统计数 */
  161.     public static long getCount(String collectionName, Bson filter) {
  162.         return getCollection(collectionName).countDocuments(filter);
  163.     }
  164.    
  165.     /** 分页查询 */
  166.     public static List<Document> findByPage(String collectionName, Bson filter, int pageNo, int pageSize) {
  167.        List<Document> results = new ArrayList<Document>();  
  168.         Bson orderBy = new BasicDBObject("_id", -1);
  169.         MongoCursor<Document> cursor = getCollection(collectionName).find(filter).sort(orderBy).skip((pageNo - 1) * pageSize).limit(pageSize).iterator();
  170.         while (cursor.hasNext()) {  
  171.             results.add(cursor.next());  
  172.         }
  173.         return results;  
  174.     }
  175.    
  176.     /** 分页查询+排序 */
  177.     public static List<Document> findByPage(String collectionName, Bson filter, Bson orderBy, int pageNo, int pageSize) {
  178.        List<Document> results = new ArrayList<Document>();  
  179.         MongoCursor<Document> cursor = getCollection(collectionName).find(filter).sort(orderBy).skip((pageNo - 1) * pageSize).limit(pageSize).iterator();
  180.         while (cursor.hasNext()) {  
  181.             results.add(cursor.next());  
  182.         }
  183.         return results;  
  184.     }
  185.   
  186.     /**
  187.      * 更新查询到的第一个
  188.      *  
  189.      * @param filter
  190.      *            查询条件
  191.      * @param update
  192.      *            更新文档
  193.      * @return 更新结果
  194.      */  
  195.     public static UpdateResult updateOne(String collectionName, Bson filter, Bson update) {  
  196.         UpdateResult result = getCollection(collectionName).updateOne(filter, update);  
  197.   
  198.         return result;  
  199.     }  
  200.   
  201.     /**
  202.      * 更新查询到的所有的文档
  203.      *  
  204.      * @param filter
  205.      *            查询条件
  206.      * @param update
  207.      *            更新文档
  208.      * @return 更新结果
  209.      */  
  210.     public static UpdateResult updateMany(String collectionName, Bson filter, Bson update) {  
  211.         UpdateResult result = getCollection(collectionName).updateMany(filter, update);  
  212.   
  213.         return result;  
  214.     }  
  215.    
  216.     /**
  217.      * FIXME
  218.      *
  219.      * @param collectionName
  220.      * @param id
  221.      * @param newdoc
  222.      * @return
  223.      */
  224.     public static Document updateById(String collectionName, String id, Document newdoc) {
  225.         ObjectId _idobj = null;
  226.         try {
  227.             _idobj = new ObjectId(id);
  228.         } catch (Exception e) {
  229.             return null;
  230.         }
  231.         Bson filter = Filters.eq("_id", _idobj);
  232.         // coll.replaceOne(filter, newdoc); // 完全替代
  233.         getCollection(collectionName).updateOne(filter, new Document("$set", newdoc));
  234.         return newdoc;
  235.     }
  236.   
  237.     /**
  238.      * 更新一个文档, 结果是replacement是新文档,老文档完全被替换
  239.      *  
  240.      * @param filter
  241.      *            查询条件
  242.      * @param replacement
  243.      *            跟新文档
  244.      */  
  245.     public static void replace(String collectionName, Bson filter, Document replacement) {  
  246.         getCollection(collectionName).replaceOne(filter, replacement);  
  247.     }  
  248.   
  249.     /**
  250.      * 根据条件删除一个文档
  251.      *  
  252.      * @param filter
  253.      *            查询条件
  254.      */  
  255.     public static void deleteOne(String collectionName, Bson filter) {  
  256.         getCollection(collectionName).deleteOne(filter);  
  257.     }  
  258.   
  259.     /**
  260.      * 根据条件删除多个文档
  261.      *  
  262.      * @param filter
  263.      *            查询条件
  264.      */  
  265.     public static void deleteMany(String collectionName, Bson filter) {  
  266.         getCollection(collectionName).deleteMany(filter);  
  267.     }
  268.       
  269.     /**
  270.      * 通过ID删除
  271.      *
  272.      * @param collectionName
  273.      * @param id
  274.      * @return
  275.      */
  276.     public static long deleteById(String collectionName, String id) {
  277.        long count = 0;
  278.         ObjectId _id = null;
  279.         try {
  280.             _id = new ObjectId(id);
  281.         } catch (Exception e) {
  282.             return 0;
  283.         }
  284.         Bson filter = Filters.eq("_id", _id);
  285.         DeleteResult deleteResult = getCollection(collectionName).deleteOne(filter);
  286.         count = deleteResult.getDeletedCount();
  287.         return count;
  288.     }
  289.       
  290. }
复制代码
 
翻译
搜索
复制

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

麻花痒

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表