关于工作中爬取网站的一些思路记录

这篇具有很好参考价值的文章主要介绍了关于工作中爬取网站的一些思路记录。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

声明:只是因为工作中需要,且基本不会对别人的网站构成什么不好的影响,做个思路记录!!!
尊重网站所有者、控制请求频率、遵守网站规则、尊重个人隐私

平常工作中难免会遇到需要爬取别人网站的需求,例如爬取兑换之类的流程,把接口爬取下来封装到项目中,这种一般不会对别人的网站有什么的影响,因为也是正常流程下单,例如下面的活动截图:
关于工作中爬取网站的一些思路记录,JAVA,java,javascript,无头浏览器

  • 1、先理解需求,从需求和界面上看,很容易知道我们基本只需要获取两个接口,一个是发送验证码接口,一个是兑换接口。当然也可能存在前置接口,具体情况具体分析
  • 2、先不要急着分析网站源码,可以先尝试找个手机号发送验证码,看看请求了哪些接口,接口的参数是什么,返回的数据是什么,例如:
    关于工作中爬取网站的一些思路记录,JAVA,java,javascript,无头浏览器
    关于工作中爬取网站的一些思路记录,JAVA,java,javascript,无头浏览器
  • 3、从请求接口的参数的返回分析,这个网站的数据部分接口需要加密,部分不需要,如果不需要加密的接口,基本很容易就获取请求参数,这里可以大胆猜测accessId、reqId可能为uuid,reqMethod为请求的方法,encrypted表示接口请求参数是否需要加密,但是光这样看有点难以看出data和dataKey是什么加密算法加密而成,dataKey大概率是解密data的关键密钥。这里建议一般情况下看一下加密后的数据的长度,是不是一些比较特殊的长度,比如36位、512位之类的长度,可以根据这个长度大胆猜测是否是平常常用的算法。
  • 4、对网站有个大概的数据交互认识之后,我们就可以知道难点基本在数据加密这一块,这时候就可以来看源码了,这里的思路我一般是直接定位到“发送验证码”的按钮上,然后找到F12控制台元素的事件监听器的click事件上,直接进入相关的代码中,就可以看到这个按钮的点击事件的代码了。
  • 5、网站的代码都是经过编译的,且一般线上是不会直接开放源代码的,这种时候如何光看编译过后的代码,有时候是比较难以理解,这种时候就需要打断点,一步步调试了,看函数的参数和返回值,以及大概的处理过程。
  • 6、前面已经分析过了,难点就在加密算法上,经过代码分析找到加密部分的代码,如下图:
    关于工作中爬取网站的一些思路记录,JAVA,java,javascript,无头浏览器
    从这段的代码中,存在RSA和AES的字眼,且打断点都走了这些函数,可以看出这个网站是AES+RSA结合使用进行加密的。

AES+RSA:使用RSA秘钥生成工具生成一对公钥(A)和私钥(B),前端保留A,后端保留B。
前端发送数据时,先生成一串随机16位字符串作为AES的秘钥(C),然后使用A使用RSA算法对C进行加密,得到加密后的AES秘钥(D)。将要发送的数据(E)用C使用AES加密,得到密文(F)。将D和F一同发给后端进行处理。
后端处理数据时,先用B对D使用RSA进行解密得到C,用C对F使用AES进行解密得到E,处理后得到结果G,再用C对G进行AES加密得到H,将H返回给前端。
前端接收到H后用C进行解密,得到处理的结果G。

根据AES和RSA的配合流程来看,这里没有直接返回RSA公钥,而是根据摸和指数来生成RSA公钥然后加密AES私钥,用AES私钥去加密数据进行传输,但是从前面请求参数来看,跟我们平常看到的AES和RSA字符串不一样,显然还做了相关的转换,dataKey字段只有数字和小写字母,平常看到的加密数据还有大写字母、+、/等。

  • 7、这里有一个比较难的地方就是“new no.RSAKeyPair(e,“”,t,2048)”这个对象,这个对象去加密随机生成的AES密钥生成dataKey字段,这里我也是看了半天,打断点半天,也难以理解,因为编译后很多变量是单个字母,且你需要换算成你自己项目的语言,如JAVA、Python等,有时候是比较难的,这时候你可能会想我能不能反编译一下js文件,那你可以尝试一下,比如找一些在线的网站上传文件看看能不能反编译,希望你能成功😂
  • 8、遇到难点无法继续下的时候怎么办呢?给大家提供一种思路,就是尝试直接拷贝它的js文件下来,然后在项目去执行它的函数,获取结果,我这里是使用JAVA、jdk1.8版本,由JavaScript引擎去执行js文件中的函数,根据上面的截图,我只需要执行Fp()函数即可拿到dataKey,和随机生成的AES私钥。
    当然你如果直接执行拷贝下来的js文件大概率是失败,会报各种错误,例如jdk1.8不支持ES6语法,你需要先转化成ES5语法格式(es6转es5在线网站:https://babeljs.io/repl,需要勾选左侧下面的"FORCE ALL TRANSFORMS"),其次你需要把不需要用到的代码都删掉,只留加密部分的代码,可以根据入口函数一步步找到所有需要的变量和函数等,可以根据报错一步步处理,这也是个小挑战~
public static void main(String[] args) {
        // 创建JavaScript引擎
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("js");

        try {
            // 加载JavaScript文件
            engine.eval(new FileReader("C:\\Users\\win\\Desktop\\index2.js"));
            // 执行JavaScript函数
            Object result = engine.eval("Fp()");
            
            // 这里是我习惯用serr打印测试日志,因为标红比较显眼
            System.err.println("Function Result: " + JSONObject.toJSONString(result));
            // 拿到Fp()函数返回的dataKey等数据
            JSONObject object = JSONObject.parseObject(JSONObject.toJSONString(result));
            // 要加密的数据
            String content = "{\"appId\":\"xxxx\"}";
            System.err.println("加密前的数据:" + content);
            // 加密后的数据
            String encryptAES = encryptAES(content, object.getString("key"), object.getString("iv"));
            System.err.println("加密后的数据:" + encryptAES);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * AES加密
     * @param plaintext 要加密的数据
     * @param key
     * @param iv
     */
    public static String encryptAES(String plaintext, String key, String iv) {
        try {
            SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
            IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);

            byte[] encryptedBytes = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
            return bytesToHex(encryptedBytes).toUpperCase();
        } catch (Exception e) {
            log.error("AES加密异常,{}", e.getMessage());
            return "";
        }
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder result = new StringBuilder();
        for (byte b : bytes) {
            result.append(String.format("%02X", b));
        }
        return result.toString();
    }
  • 9、终极方案:无头浏览器!!!如果上面还不能解决你的问题,你可以尝试使用无头浏览器,模拟人工点击操作,当然这比接口慢很多,但你不需要考虑网站的加密和接口调用等等,按照人工操作的流程执行即可。注意,无头浏览器你可能需要考虑代理ip和请求头问题,尽可能模拟真实的操作,一直使用同一个ip和userAgent有可能会被检测到。
/**
     * 获取浏览器驱动
     */
    private WebDriver getDriver(Param pm) {
        // 设置随机的设备 user-agent 和屏幕大小
        Map<String, Object> mobileEmulation = new HashMap<>();
        Map<String, Object> map = new HashMap<>();
        Dimension randomScreenSize = getRandomScreenSize();
        map.put("width", randomScreenSize.getWidth());
        map.put("height", randomScreenSize.getHeight());
        mobileEmulation.put("deviceMetrics", map);
        if (pm != null && Func.isNotBlank(pm.getUserAgent())) {
        	// 设置UA
            mobileEmulation.put("userAgent", pm.getUserAgent());
        }

        //谷歌浏览器设置
        ChromeOptions options = new ChromeOptions();
        // 隐藏浏览器、无头浏览器
        options.addArguments("-headless");
        options.setExperimentalOption("mobileEmulation", mobileEmulation);
        // 打开F12
//        options.addArguments("--auto-open-devtools-for-tabs");
        // 启动无沙盒模式运行,以最高权限运行
        options.addArguments("--no-sandbox");
        // 不加载图片, 提升速度
        options.addArguments("blink-settings=imagesEnabled=false");
        
        options.addArguments("--disable-dev-shm-usage");
        // 禁用gpu渲染
        options.addArguments("--disable-gpu");
        // 禁用阻止弹出窗口
        options.addArguments("--disable-popup-blocking");
        // 禁用扩展
        options.addArguments("disable-extensions");
        // 禁用默认浏览器检查
        options.addArguments("no-default-browser-check");
        // 忽略不信任证书
        options.addArguments("–ignore-certificate-errors");
        // 禁用自动化控制特性
        options.addArguments("--disable-blink-features=AutomationControlled");
        // 禁用通知
        options.addArguments("--disable-notifications");
        // 禁用信息栏
        options.addArguments("--disable-infobars");
        // 禁用日志记录
        options.addArguments("--disable-logging");

        LoggingPreferences logPrefs = new LoggingPreferences();
        logPrefs.enable(LogType.PERFORMANCE, Level.ALL);
        options.setCapability("goog:loggingPrefs", logPrefs);

        // 禁用默认应用程序
        options.addArguments("--disable-default-apps");
        // 静音
        options.addArguments("--mute-audio");
        // 禁用自动化标志
        options.setExperimentalOption("excludeSwitches", new String[]{"enable-automation"});

        // 设置代理ip
        if (pm != null && Func.isNotBlank(pm.getProxyIp())) {
            String proxyAddress = pm.getProxyIp() + ":" + pm.getProxyPort();

            Proxy proxy = new Proxy();
            proxy.setHttpProxy(proxyAddress);
            proxy.setSslProxy(proxyAddress);
            options.setProxy(proxy);
        }
        return new ChromeDriver(options);
    }

谷歌浏览器驱动路径:https://googlechromelabs.github.io/chrome-for-testing/#stable文章来源地址https://www.toymoban.com/news/detail-729028.html

public void handle(Param pm) {
        WebDriver driver = null;
        try {
            if (Func.isBlank(pm.getUserAgent())) {
            	// 这个工具类只是随机生成userAgent的工具类
                pm.setUserAgent(UserAgentUtil.getUserAgent());
            }
			// 谷歌浏览器驱动路径,注意驱动版本问题
            System.setProperty("webdriver.chrome.driver", "F:/chromedriver-win64/chromedriver.exe");
            driver = getDriver(pm);
//            driver.manage().window().maximize();
            // 进入页面
            driver.get("https://xxx");

            JavascriptExecutor js = (JavascriptExecutor) driver;
            //添加cookie
            if (pm.getCookies() != null && pm.getCookies().size() > 0) {
                setCookie(js, pm.getCookies());
            }
            // 隐式等待
            driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

          	// 其他相关处理代码
          	...
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (driver != null) {
                driver.quit();
            }
        }
    }

到了这里,关于关于工作中爬取网站的一些思路记录的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 关于信息学奥赛中的一些做题思路

    本文记录了笔者在刷题或比赛中运用到的一些做题思路 可以 适当 参考 首先显然有 (mathcal {O}(n^2)) 暴力 枚举每个子段,然后选择其中前k大的 那么可以发现有 贪心 策略: 选择k次最大值 那么考虑怎样求最大值 想到可以枚举每个起始位置,想办法计算从该位置开始符合要求

    2024年03月13日
    浏览(44)
  • 关于网络安全运营工作与安全建设工作的一些思考

    以下内容是个人成长过程中对于网络安全运营工作的理解和思考,希望通过这篇文章帮助大家更好的去做安全运营体系化建设,开始吧! 安全运营工作并不是通过各类安全设备的叠加增强安全能力,而是通过技术与管理结合的形式将企业现有的安全能力进行最大化展现。为了

    2024年02月04日
    浏览(37)
  • 【工作记录】基于可视化爬虫spiderflow实战天气数据爬取@20230618

    之前写过一篇关于可视化爬虫spiderflow的文章,介绍了基本语法并实战了某校园新闻数据的爬取。 还有一篇文章介绍了基于docker-compose快速部署spiderflow的过程,需要部署的话可参考该文章。 文章链接如下: 可视化爬虫框架spiderflow入门及实战 【工作记录】基于docker-compose快速部

    2024年02月11日
    浏览(66)
  • 【复现go语言编写的区块链PBFT共识算法中爬坑记录】

    先附上代码链接:https://github.com/corgi-kx/blockchain_consensus_algorithm/tree/master/pbft 主要是想记录一下运行代码过程中遇到的问题,万一以后用得到,还能抄一下作业 电脑上没有go语言环境,按下面步骤进行环境配置: 1、首先在go官网下载https://golang.org/dl/安装包,根据自己电脑选择

    2024年01月25日
    浏览(40)
  • 关于laravel使用Elastic Search的一些记录

    1. 准备工作 因为我本地php版本是7.3.4,不支持太高的es。 所以使用如下环境: laravel6 + php7.3.4 + elastic search 7.17.2 2. 本地安装elastic search 注意事项: 如果是8以上版本,初次启动时会生成密码。安装成功以后,访问 https://localhost:9200/ ,会提示输入密码。用户名为elastic,密码就是

    2024年02月11日
    浏览(42)
  • JAVA刷题之字符串的一些个人思路

    感谢您的阅读! ꒰˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好,我是xiaoxie.希望你看完之后,有不足之处请多多谅解,让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN 如需转载还请通知˶⍤⃝˶ 个人

    2024年02月05日
    浏览(31)
  • 关于Java注解的一些理解 小结

    目录 1. 常用注解和理解 2. 自定义注解 2.1 案例背景 2.2 设计思路 3 总结 注解在我的理解下,就是代码中的特殊标记,这些标记可以在 编译、类加载、运行时 被读取,并执行相对应的处理。 可能有些抽象,简单来说注解其实在开发中是非常常见的,比如我们在使用各种框架时

    2023年04月23日
    浏览(32)
  • 工作三年后, 我作为Java后端开发的一些心得

    敢于和善于使用package 对于Java后端开发来讲, 在长时间的web开发中. 大家已经熟悉了MVC架构, 也被这套结构所束缚. 导致创建出来的包也一直都是controller, manager, service, dao. 也将各种各样的类文件都放入其中. 这并不是一种好的做法. 其实我们可以大胆的创建相关的package, 只要让

    2024年02月13日
    浏览(25)
  • 请问一下java在线编程的网站有哪一些?

    前言 下面为大家整合了一些Java在线编程的的网站,个人认为都是挺好用的,整合不易,希望大家能顺手留下点赞和收藏! 废话少说,我们直接进入正题: 1、菜鸟工具 菜鸟工具的这个在线编程工具页面很为简洁,写代码的区域和结果输出的区域很清晰,可以下载当前编辑的

    2024年02月16日
    浏览(21)
  • 关于Java中@Transient主键的作用的一些介绍

    @Transient 主下面是关于 @Transient 主键的使用方法、代码案例以及与 transient 的区别,以及一些实用场景的详细介绍。 在实体类中,通常需要将某些字段标记为主键,并将其映射到数据库中的主键字段。但是,有时候我们可能希望某个字段在实体类中作为主键使用,但不

    2024年02月10日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包