Jsoup 网路爬虫 实战使用

Jsoup 网路爬虫 实战使用

“硬盘有价数据无价” , 程序 = 数据结构 + 算法 , 计算机的诞生时主要作用在于辅助数据运算,任何能被计算机采集存储的信息都为数据. 而数据的价值是有区别的,推荐算法,程序预警往往是基于已有数据和算法去实现的,当然最浅显的说就是值钱.

当然从另一种角度上来说,就是凡是能通过固定流程处理的东西,都可以程序化,而凡我们可以手动操作电脑或者类似设备实现的东西都可以程序化. ps: 程序不一定是最高效的解决方案,我想起有个老师问我的问题了,我可以一个 excel 解决的事情为什么要用程序 (_)

好吧,说正事,场景就是 gpt 火了,公司也做了相关的业务,大体就是利用开源项目自己训练辅助模型,弄个智能客服哪一类的,而算法那面训练的时候需要有一些在政务网可查的数据,录入到图数据库中

大数据的四个基本特征

  • 数据量大(Volume)
  • 数据种类多(Vari⁃ety)
  • 数据价值密度低(Value)
  • 以及数据产生和处理速度快(Velocity)

g 我又不是大数据科班出身的,不过总结一下这几个月的经验就是

  • 数据有好有坏
  • 数据来源有自己项目产生
  • 其他系统接口授权(共享平台)
  • 数仓权限申请
  • 可以通过 技术手段/人力手段 搜集互联网公开数据
  • 数据具有时效性,有些数据同步过来时间太长就没啥用了(ps:当时哥说我们自己爬,能不能不要授权,我丢,哪个数据量可是老大了,而且嗯数据保密啊,不和规矩)
  • 数据具有保密性,对这个很重要,数据安全真的贼重要,每一次大规模的用户数据泄露都很麻烦,就想想吧,假如你的网购记录对你在意的人公开,或者某些嗯记录,我一直感觉我在互联网上裸奔 (社会工程 安全体系中人的漏洞 , 这本书相当推荐,细节控标示学到了)

因为要录入数据嘛,刚开始看了一下 cql 的语法,虽然记不住但类比一下大差不差照猫画虎就写了点测一下正常,然后嗯看了下数据量也就中等意思,然后就去网站手摘放到 excel 中, 用 easyexcel 导到 内存中 根据 freemarker 去拼接好处理好的 String 写入到一个 txt 文本中就好了,然后任务完成,但是隔了一段时间又有其他数据需要入库,大概是十张页面的数据的一部分,这回手动去摘抄到 excel 中很遭罪.所以使用了爬虫技术.

什么是爬虫

爬虫(Web Crawler)是一种自动化程序,也称为网络爬虫、网络蜘蛛或网络机器人,它们被设计用于自动地浏览互联网上的网页并收集信息。爬虫以一种系统化的方式遍历互联网,访问网页并获取页面内容,然后将这些数据传递给搜索引擎或其他应用程序进行处理、索引或分析。

爬虫的工作原理是通过遵循超链接来跟踪网页之间的链接,从一个页面获取链接,再通过这些链接找到其他页面。它们收集的数据可以用于不同的用途,例如搜索引擎的网页索引、数据挖掘、分析和展示等。

爬虫在互联网上发挥着重要的作用,帮助搜索引擎发现、索引和提供网页,以便用户能够通过搜索引擎找到他们需要的信息。同时,爬虫也可能被用于其他目的,例如抓取数据以进行竞争情报、价格比较、内容聚合等。

看得出来,其主要作用就是针对于网路上数据

那是否能从网页上通过机器手段获取数据的都算爬虫那?

在这里插入图片描述

爬虫的目的也应对爬虫的方案

我也不是专业学爬虫的,只是完成任务的时候有需要,所以嗯简单带过

  1. 核心,爬虫是获取数据的自动化工具,不是产生数据的
  2. 合规,爬虫要符合相应数据提供商的规范,不可以对系统造成破化
  3. 不能碰机密数据,啊也不要用公开数据赚钱

上面的原则是不可改变的,不然容易吃牢饭,当然那是非专业的底线,谨小慎微足够尊重法律

简单的反扒手段

数据加密传输,防止直接通过接口请求 + 参数的形式轻松获取数据

参数限定,增加爬取难度,比如入参参数, + 预警机制

加入参参数 + 加一些不明所以的参数,嗯混淆视听增加爬取难度, 勤换参数,只要条件不同意编码起来难度剧增

身份验证: 身份验证加时效,勤刷新,数据分级做验证

日志: 请求日志记录唯一性信息 (比如用户身份 用户 ip 及时封号封 ip)

当然,处理起来越麻烦越安全,成本越高,甚至有些会影响性能

当然,直接白名单 ip + 局域网 能搞定 九成八

爬虫开发注意事项
  • 减少数据获取次数,不要给他人服务器带来压力
  • 多用户模式 , 不要可这一个账号爬数据,chat-gpt 刚火的时候的共享平台,就是多账号模式,通过增加账号减少被封号风险.(当然多 ip 也算一个思路了)
  • 时间范围问题,当出现问题后最先查的 日志时间一定是整点数据和固定间隔数据,因为 cron 表达式写的越花越难搞. 可以加个 sleep 睡眠随机值(gpt 刚出的时候连着 AI 写情书,想做个定时群发情书邮件的代码(晚 8-10 点间发),后来成了,但是没扩展,只能单人使用,然后情书也变成了祝福,但 AI 调用上限到了之后就没有搞)
  • 热门信息存储,如果不是定期的爬取的话,爬取数据不确定,可以先统计前一天查询频率高的数据,提前在对方系统调用少的时间段调用本地存储,减少热门信息对对方服务器带来的压力
  • 限流,对限流,不管是定时调用 ,还是通过 sleep 来模拟人调用总会确定大概调用频率,对对方服务器的压力是有限的,但当完全时时获取数据后,我们的系统会不会被攻击,从而影响到对方系统就不一定了,所以也得做反扒,套娃;
具体实践
  1. /robots.txt

    这是决定吃不吃牢饭,吃多少的关键,域名 + /robots.txt ,当然这个只是建议,少量的获取数据,我不想复制黏贴那种,也没啥,嗯我正常请求啊.

    在这里插入图片描述

  2. 通过 http 请求模拟用户行为获取数据,从中截取需要的

    f12 看到的数据为正常所需要的数据使用这种方法,当然就是用各种工具发请求就好了,爬虫的难点在找到能用的数据,和获取相应地权限,但重中之重在于不进局子.

    这段请求有好多工具都支持,核心就是模拟用户行为去发请求就好了

    String body = HttpRequest.get(url2)
            .execute()
            .body();
    
  3. 如果加密了,请求回来的东西看不懂,或者是一堆代码,没有实质信息

    就从渲染好的 html 文件中获取

    至于 jsoup 的 api 我就随手搜了几个看了下就用了,很简单的

    使用了 Java 的 jsoup 库,获取 Document ,从标签中寻找 我想要的信息,处理组装,当然这个代码仅仅是我刚写的一部分测试代码,实际上整理了一个 excel 用错需要请求的页面,还有在系统内部id 标示的字段,通过导入对象循环爬取数据写入 最后要处理的列表统一生成 cql

    然后处理为我想要的格式填到 cql 模板里,其实可以直接读取 cql 执行

    <dependency>
        <groupId>org.jsoup</groupId>
        <artifactId>jsoup</artifactId>
        <version>1.15.3</version>
    </dependency>
    
    String url2 = String.format("https://www.zjzwfw.gov.cn/zjservice/item/detail/index.do?localInnerCode=9392a880-a166-4413-857b-3ff4921942c1&webId=1");
            String C = "arialoadData=false; zh_choose_undefined=n; cna=BqkWHhGJEx0CAf+Z/Pm9; _ud_=16293bf89b71451aaa91d4c38ea7e088; aliyungf_tc=278dfc45157d55f9044ffe6edf9672fc1e1e7f8d3db78c61c9a933082f1ccf17; acw_tc=ac11000117039933109205031e6781887464728a3f8b2fb5b8e69092f3091a; ZJZWFWSESSIONID=50db77d6-d130-49ae-907d-edb0f550f113; session=a88e4f95cdb54bb48b37f6eaa7a894e4; webId=1; zjzw_siteCode=330000000000; acw_sc__v2=6590e003d043ff24376b4c4a8dd52e104ee3d41a; zwlogBaseinfo=eyJsbF91c2VyaWQiOiIiLCJsb2dfc3RhdHVzIjoiIiwidXNlclR5cGUiOiJndWVzdCIsImJpel9zZXNzaW9uX2lkIjoiYTg4ZTRmOTVjZGI1NGJiNDhiMzdmNmVhYTdhODk0ZTQiLCJzaXRlX2lkIjoiMzMwMDAwMDAwMDAwIiwicGFnZV9tb2RlIjoi5bi46KeE5qih5byPIn0%3D; ssxmod_itna2=Yu0=GKDK7KAIjxlSD+obdQitSpTqGqG=qr8PD6hKIDpD05awY03mPnjUXonZ8lAxAP39KemY6KYd4jHb32lOwo6APM1A8nvPc+c8cwGN9p9+6aPo6yBhq4qKIOyZINjYHl2vFzXzA7wKy4mtxxQXnDqr/b4IPp3oVe4UL9LUKTjYoPMPB4Cu3alXYhq6qK4vp/WTbs4t4d8bBGhcKP1Tj3=jNEPorspHbVCh04tfzXaODhTdWPfIM4m7hPf7IL/8NXeE+L1Y6E/ANLOR0su70qMOCDWM+P4c25fKm5fh0eEKLTDaZwjzYxaNSzaw4GioYxseWYBuziL757DADDwxqDjKDedx4D==; ssxmod_itna=eqUxuQGQeiubDX7q7xDwxmTIO766f3D/KDfx4iNDnGD8hxD5dAeLeTL7+2Cw3TKD7uA74OQ+xvreKGnRY8WDCPGnDBIhea94YYDtxBYDQxAYDGDDPDo1PD1D3qDkD7gCMBRTqi3DECKGfDDoDYSj0DitD4qDBFE3DKqGgtTYqji=dDDNdSewRRDDh/w0fietY1uD457GuD0toxBdTmPTKv6Fdjw0ak6Xr4qGyeKGumqUMU4bDCr=lILX8i3xKGGIe+x4T3xh7BDwwfBR77iYQ9x4q43qwKRKrmS8xD==";
            Document doc = null;
            try {
                doc = Jsoup.connect(url2).cookie("Cookie", C).get();
            } catch (IOException e) {
            }
            Elements clearfix = doc.getElementsByClass("offline-office clearfix");
    
            ArrayList<OfflineHandlingOfPower> offlineHandlingOfPowers = new ArrayList<>();
    
    
            for (Element element : clearfix) {
                Elements S = element.select("具体地址");
                Elements clearfix1 = element.getElementsByClass("offline-office-textNew");
                String metainformation = clearfix1.text();
                OfflineHandlingOfPower offlineHandlingOfPower = new OfflineHandlingOfPower();
                String[] lxdh = metainformation.split("联系电话:");
                String[] split = lxdh[0].split("办理时间:");
                String trim = split[0].replace("具体地址:", "").trim();
                offlineHandlingOfPower.setQl_inner_code("1");
                offlineHandlingOfPower.setName(trim);
                offlineHandlingOfPower.setProcess_time(split[1].trim());
    
    
                offlineHandlingOfPowers.add(offlineHandlingOfPower);
            }
            offlineHandlingOfPowers.forEach(System.out::println);
    
            String projectPath = System.getProperty("user.dir");
            String inputPath = projectPath + File.separator + "src/main/resources/templates/cql/CqlCreateNode.ftl";
            String outputPath = projectPath + File.separator + "src/main/resources/generate/cql/createCql.txt";
            // new 出 Configuration 对象,参数为 FreeMarker 版本号
            Configuration configuration = new Configuration(Configuration.VERSION_2_3_32);
    
            // 指定模板文件所在的路径
            File templateDir = new File(inputPath).getParentFile();
            configuration.setDirectoryForTemplateLoading(templateDir);
    
            // 设置模板文件使用的字符集
            configuration.setDefaultEncoding("utf-8");
    
            // 创建模板对象,加载指定模板
            String templateName = new File(inputPath).getName();
            Template template = configuration.getTemplate(templateName);
    
            StringWriter stringWriter = new StringWriter();
            HashMap<String, Object> mindle = new HashMap<>();
            mindle.put("entityList", offlineHandlingOfPowers);
            template.process(mindle, stringWriter);
            String generatedCode = stringWriter.toString();
            // Write generated code to a file
            try (FileWriter fileWriter = new FileWriter(outputPath, true);
                 PrintWriter printWriter = new PrintWriter(fileWriter)) {
                printWriter.println(generatedCode);
            } catch (IOException e) {
                e.printStackTrace();
            }
    
  4. 如果是那种边看边加载,分小片反复验那种

    洗洗睡吧,我不是专门做爬虫的

补一张图

HAR 格式的文档可能泄露个人铭感身份信息,不过,如果玩爬虫的话保存 HAR 格式文件,从其中调取用到的参数比直接上肉眼看着快得多,可以百度了解下这个文件的格式和对应记录的信息.
在这里插入图片描述


总结

简单的爬虫真的很简单,但是安全合规和对数据的处理反而是很麻烦的,一切用户所能见到的数据都可以通过技术手段获取,当然,其实用户看不见的数据互传也能获取,实在不行物理入侵,没有绝对安全的系统,有的只是程序员的与空气搏斗,多想到了就能多一层安全,谨慎一些就可能少吃一口皇粮,保护数据的安全和带来更好的使用体验,解放双手,解放流程性的枯燥才是编程应该实现的目标,绝不仅仅是写出更帅的代码;有些东西用户使用体验好无非就是先做一部,而这一步往往是数据做支撑,爬虫嗯友好又坏,其实过程是很枯燥的,要一点点点的猜测别人的实现,通过 浏览器的一些工具去确定参数,接口范围,猜大概实现,找到自己能用的数据,然后通过代码去清洗.

能用工具先用工具,工具不行上人工,在写这个之前我想要自动获取 cookie ,想用 selenium 去实现,但是啊适配问题,我找不到对应的版本,安装了好几,狂躁,各种问题,连续几个小时,有的时候怀疑人生,虽然最后没搞定,但是也学到了很多东西,也暴露了我嗯有些地方还是存在坑,需要回去填. 嗯共享开放平台也可以共享数据啊,硬盘有价数据无价.
不过有时候最简单的解决方案就是人工啊,哈哈哈哈哈哈;

本期坑

Java 使用 neo4j
selenium 使用
http 等网络协议深入理解
数据清洗落库
数据类型和更多数据处理方面的知识

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值