RPC通用爬虫

news2024/12/23 6:17:00

文章目录

  • RPC通用爬虫
    • 一、项目案例
    • 二、Rpc原理解析
    • 三、Rpc代码分享
    • 四、自我总结

RPC通用爬虫

一、项目案例

在这里插入图片描述

  • 测试网址: aHR0cDovL3d3dy5mYW5nZGkuY29tLmNuL3NlcnZpY2UvYnVsbGV0aW5fbGlzdC5odG1sP3R5cGVhPWI2N2MzYjhhZGJkY2U3NGQ=

二、Rpc原理解析

在这里插入图片描述

图解关系:

​ 主要包括,爬虫程序、Web服务器、WebScoket服务器、浏览器

核心流程:

​ 爬虫程序调用服务器,可传入参数给服务器,服务器接收到参数后创建一个WS连接,连接到WebSocket服务器;WebSocket服务器其实什么都没有做,就是将消息传递浏览器。因为我们提前替换一些代码,相当于进行hook(找到参数加密解密逻辑,然后利用window定义全局变量),后续传递消息给浏览器,让它帮助我们完成加密解密的工作。将加密参数或是解密参数结果直接返回,发送给WebSocket服务器,最后经过Web服务器返回给我们的爬虫,继续请求服务器获取数据。

启动顺序:

​ 1.WebSocket服务器;

​ 2.断点浏览器,注入JS代码 建立与WS的连接;

​ 3.Web服务器开启等待请求,建立WS连接;

​ 4.Spider调用服务器接口;

三、Rpc代码分享

  • WebSocket服务器

    '''
    模块依赖
    pip install websockets
    pip install sanic
    '''
    import re
    import asyncio
    import websockets
    
    # TODO: 消息转发 握手原则
    BROWSER_KEYWORD = "regist"
    PYTHON_SERVER_KEYWORD = "sanic2"
    # ws链接内存存储
    browser_info: dict = {}
    sanic_info: dict = {}
    
    async def dispatch_action(ws, path):
        """
        请求分发,存储不同的连接
        :param ws: 服务器与连接对象的连接
        :param path: 请求路径
        :return:
        """
        # action_name 标识 连接对象身份 ...
        re_result = re.compile("/(?P<action_name>.*?)\?name=(?P<proj_name>.*)").search(path)
        action_name: str = re_result.group("action_name")
        proj_name: str = re_result.group("proj_name")
    
        # 连接保存 对应存储连接对象 {}
        if action_name == PYTHON_SERVER_KEYWORD:  # Python
            sanic_info[action_name] = ws
        elif action_name == BROWSER_KEYWORD: #  browser
            browser_info[action_name] = ws
        return action_name
    
    
    async def handler(ws, path):
        """
        主要处理ws请求
        :param ws:服务器与连接对象的连接
        :param path: 请求路径
        :return:
        """
        action_name = await dispatch_action(ws, path)
        print("有人来了: =>>>", action_name)
        # 收到数据,转发数据 可以基于Json
        async for msg in ws: #msg 参数 或者是 返回值
            # 请求控制
            if action_name == PYTHON_SERVER_KEYWORD:
                # 发送给浏览器 连接对象
                await browser_info[BROWSER_KEYWORD].send(msg)
            # 返回加密结果
            elif action_name == BROWSER_KEYWORD:
                # 发送给服务器 连接对象
                await sanic_info[PYTHON_SERVER_KEYWORD].send(msg)
    
    async def main():
        async with websockets.serve(handler, "127.0.0.1", 8868) as rpcfucktheworld:
            print("webScoketServer start ...")
            await asyncio.Future()
    
    
    '''
    启动的顺序很重要
    1.websocketserver
    2.browser
    3.webserver
    4.spider
    
    process:
    spider <=> webserver <=> websocketserver <=> browser 
    '''
    
    if __name__ == '__main__':
        asyncio.run(main())
    
    
  • Browser浏览器

        (function (){
            // 建立连接
            const socket = new WebSocket('ws://127.0.0.1:8868/regist?name=ooxx');
        // 接收到消息时的回调函数
            socket.addEventListener('message', function (event) {
                const obj = JSON.parse(event.data);
    
                // obj 所有的参数
                console.log("参数来了:", obj)
                // 植入js代码搞一波....
                window.FUCK1();
                const result = {
                    // any you want to return value...
                    "MmEwMD":window.FUCK2(obj.url),
                    "cookie": document.cookie,
                }
                console.log("数据打包回家:", result)
                    socket.send(JSON.stringify(result));
            });
        })()
    
    
  • WebServer服务器

    '''
    第三方模块下载:
    pip install websockets
    pip install sanic
    '''
    import json
    import websockets
    from sanic.request import Request
    from sanic.response import text
    from sanic import Sanic
    
    app = Sanic(__name__)
    
    # http://localhost:8089/getSign?projName=ooxx
    
    # TODO:初步完成一部服务器的搭建 简易版本 支持传参 针对某一个项目
    
    @app.route("/getSign", methods=["GET", "POST"])
    async def get_sign(request: Request):
        proj_name = request.args.get('projName')
        if not proj_name:
            raise Exception("请输入项目名称!")
    
        proj_params: dict = request.json
        print("来了:", proj_params, type(proj_params))
        async with websockets.connect("ws://127.0.0.1:8868/sanic2?name={}".format(proj_name)) as ws:
            await ws.send(json.dumps(proj_params))
            result = await ws.recv()
            return text(result)
    
    if __name__ == '__main__':
        app.run(host="127.0.0.1", port=8089, debug=True)  # spider view
    
    
  • Spider爬虫程序

    import json
    import requests
    import time
    
    
    
    class PinduoduoSpider():
        def __init__(self):
            self.page = 1
            self.url = "https://脱敏处理/spike_list"
            self.headers = {
                ......
            }
    
        def get_anti_content(self):
            anti_content = requests.get("http://脱敏处理/getSign?projName=脱敏处理").json()["data"]
            return anti_content
    
        def task(self):
            response = requests.get(self.url, headers=self.headers, params={
                "page": self.page,
                "size": "50",
                "anti_content": self.get_anti_content()
            })
    
            print(response.json())
    
        def run(self):
            while True:
                self.task()
                print("当前页码:" + "=" * 20 + '>>>', self.page)
                self.page += 1
                time.sleep(2)
    
    
    if __name__ == '__main__':
        脱敏处理().run()
    
    

四、自我总结

1、关于爬虫这件事:
通过对RPC框架进行学习,我发现如果我们越了解服务器架构,后端开发,运维开发,就越有认知和思想。
例如:Scrapy分布式 采用Redis作为消息队列,可以开启多个Scrapy爬虫程序对指定网站进行数据抓取。优点:支持断点续爬虫,可以持续不断的采集数据,worker处于阻塞状态,等待任务到来然后执行对应的爬虫逻辑,这为抓取成千上万的数据提供了结实的基础。利用Redis里面的集合,我们可以对数据进行去重,从而保证了数据的唯一性;利用Redis里面的列表,我们可以实现消息队列,对请求对象进行排序,更多精彩部分在下期分享。

2.RPC运用场景:
当你找到了参数加密或解密位置,但是其逻辑非常复杂你就可以使用RPC搭建一套服务器框架,快速远程调用获取想要的参数。

3.RPC优缺点:
RPC优点>: 不用逆向了,直接获取结果,直接拿到结果,逻辑非常简单依赖网络协议,各个程序之间的通信。
RPC缺点>: 采集速度太慢,性能不好,速度不够快,只能暂时解决问题,采集更多的数据有一定的困难;必须开启本地浏览器(or selenium模拟),浪费资源。
列,对请求对象进行排序,更多精彩部分在下期分享。

2.RPC运用场景:
当你找到了参数加密或解密位置,但是其逻辑非常复杂你就可以使用RPC搭建一套服务器框架,快速远程调用获取想要的参数。

3.RPC优缺点:
RPC优点>: 不用逆向了,直接获取结果,直接拿到结果,逻辑非常简单依赖网络协议,各个程序之间的通信。
RPC缺点>: 采集速度太慢,性能不好,速度不够快,只能暂时解决问题,采集更多的数据有一定的困难;必须开启本地浏览器(or selenium模拟),浪费资源。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/628578.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Dockerfile应用的容器化

文章目录 Dockerfile应用的容器化应用的容器化——简介应用的容器化——详解单体应用容器化获取应用代码分析Dockerfile容器化当前应用/构建具体的镜像推送镜像到仓库运行应用程序测试总结 最佳实践利用构建缓存合并镜像 命令总结 Dockerfile应用的容器化 Docker 的核心思想是…

为什么网络安全缺口大,招聘却很少?

2023 年我国网络空间安全人才数量缺口超过了 140 万&#xff0c;就业人数却只有 10 多万&#xff0c;缺口高达了 93%。这里就有人会问了&#xff1a; 1、网络安全行业为什么这么缺人&#xff1f; 2、明明人才那么稀缺&#xff0c;为什么招聘时招安全的人员却没有那么多呢&am…

头部大模型公司进京赶考,向量数据库成为应考神器

日前&#xff0c;由品玩主办的「模型思辨」国内大模型产业生态研讨会在北京举办&#xff0c;Zilliz 与 360 集团、阿里巴巴、昆仑万维等来自大模型产业链的头部公司及投资机构参会&#xff0c;会上 Zilliz 创始人兼首席执行官星爵、360 集团创始人周鸿祎、昆仑万维创始人方汉等…

C++ 类设计的实践与理解

前言 C代码提供了足够的灵活性&#xff0c;因此对于大部分工程师来说都很难把握。本文介绍了写好C代码需要遵循的最佳实践方法&#xff0c;并在最后提供了一个工具可以帮助我们分析C代码的健壮度。 1. 尽可能尝试使用新的C标准 到2023年&#xff0c;C已经走过了40多个年头。新…

如何进行微服务测试?

微服务测试是一种特殊的测试类型&#xff0c;因为它涉及到多个独立的服务。以下是进行微服务测试的一般性步骤&#xff1a; 1. 确定系统架构 了解微服务架构对成功测试至关重要。确定每个微服务的职责、接口、依赖项和通信方式。了解这些信息可以帮助您更好地规划测试用例和测…

day09——线性回归

线性回归 一、什么是线性回归1&#xff0c;定义与公式2&#xff0c;线性回归的特征与目标的关系 二、线性回归的损失和优化原理1&#xff0c;损失函数2&#xff0c;优化算法 三、API四、实操&#xff1a;波士顿房价预测1&#xff0c;数据来源&#xff1a;scikit-learn2&#xf…

Acgis中实现栅格经纬度和行政区关联

写在前面 我是一个Acgis小白&#xff0c;写这篇博客是为了记录完成过程&#xff0c;如果有更高效的办法欢迎分享~ 我用的是Arcgis10.2。 需求描述 目前已有意大利的shp文件&#xff0c;希望将意大利划分成0.1*0.1经纬度的栅格&#xff0c;并且关联每个栅格中心点所属的省份信…

DBeaver复制数据库(数据库表结构以及内容)

一、 首先先建立一个数据库 &#xff08;已有请忽略此步骤&#xff09; &#xff08;名字 字符集等按需要自己填写&#xff09; 二、选择要复制的数据库 2.1右键选择 工具->转储数据库 2.2选择要导出的数据 2.3 选择要导出的路径 2.4 点击开始&#xff0c;等待导出完…

Revit中绘制弯曲的靠背栏杆和生成过梁

一、Revit中怎么绘制弯曲的靠背栏杆 栏杆通常我们见过位于在阳台处&#xff0c;但是在我们的古建筑中很常见到一种靠背栏杆&#xff0c;例如凉亭里面就很常见这种栏杆。那么如何绘制呢? 利用公制栏杆——支柱进行绘制 要运用放样工具进行绘制&#xff0c;设置一个工作平面&…

中国电子学会2023年05月份青少年软件编程Scratch图形化等级考试试卷四级真题(含答案)

2023-05 Scratch四级真题 分数&#xff1a;100 题数&#xff1a;24 测试时长&#xff1a;90min 一、单选题(共10题&#xff0c;共30分) 1. 下列积木运行后的结果是&#xff1f;&#xff08;B&#xff09;&#xff08;说明&#xff1a;逗号后面无空格&#xff09;&#xff…

mysql join 与 拆分成单表查询如何选择

参考以下文章&#xff0c;不错 数据库联表查询时&#xff0c;是直接使用join好还是分别查询到数据后自己处理较好&#xff1f; - 知乎 一&#xff0c;声明 1&#xff0c;数据量 首先场景是多个表数据量比较大&#xff0c;可能达到百万级 2&#xff0c;结论&#xff1a;最…

springboot项目启动指定对应环境的方法

1. 多环境准备 今天教大家一种多环境profile的写法&#xff0c;当然也可创建多个yml文件。如下所示&#xff1a; spring:application:name: cms-discovery-eureka-ha --- # 区分多环境 spring:profiles: peer1 server:port: 9092 eureka:in…

十、ELK安装ElastAlert 2插件飞书机器人告警(docker)

实现效果 1.创建相应挂载目录和文件 可任意位置&#xff0c;挂载对上就行&#xff0c;方便直接在宿主机修改配置。 /data/feishu-alert/config.yaml /data/feishu-alert/rules 2.编写config.yaml配置文件(/data/feishu-alert/config.yaml) #指定告警文件存放目录 rules_fo…

从C语言到C++_16(list的介绍和常用接口函数)

目录 1. list 介绍和简单使用 1.1 list介绍 1.2 list简单接口函数 1.3 push_back 和遍历 1.4 list常规接口函数使用 2. list 的其它接口函数 2.1 splice 接合 2.2 remove 删完一个值 2.3 sort和reverse 本章完。 list是个双向带头循环链表。 带头双向循环链表我们在…

21份软件测试全流程文档模板(标准版)

1、需求说明书 2、功能测试计划 3、功能测试用例 4、业务流程测试用例 5、系统安装配置说明书 6、阶段功能测试报告 7、性能测试计划 8、性能测试用例 9、性能测试报告 10、系统功能测试报告 11、需求变更说明书 12、用户建议说明书 13、验收测试报告 14、产品发布说明书 15、系…

redis下载安装

本文主要介绍如果在Centos7下安装Redis。 1.安装依赖 redis是由C语言开发&#xff0c;因此安装之前必须要确保服务器已经安装了gcc&#xff0c;可以通过如下命令查看机器是否安装&#xff1a; <span style"color:#000000"><span style"background-c…

Matlab论文插图绘制模板第101期—人口金字塔图

在之前的文章中&#xff0c;分享了Matlab双向柱状图的绘制模板&#xff1a; 进一步&#xff0c;再来分享一种特殊的双向柱状图&#xff1a;人口金字塔图。 先来看一下成品效果&#xff1a; 特别提示&#xff1a;本期内容『数据代码』已上传资源群中&#xff0c;加群的朋友请自…

Lecture 17 Machine Translation

目录 Statistical MTNeural MTAttention MechanismEvaluationConclusion Machine translation (MT) is the task of translating text from one source language to another target language why? Removes language barrierMakes information in any languages accessible t…

Polarion工作流插件(自定义)

创建插件命名插件配置插件Condition&Function package com.polarion.capital.example.conditions;import com.polarion.alm.tracker.model.IWorkItem; import com.polarion.alm.tracker.workflow.IArguments; import com.polarion.alm.tracker.workflow.ICallContext; impo…

TIME_WAIT的处理方式

TIME_WAIT 是什么 TIME_WAIT 是指在 TCP 连接关闭时&#xff0c;等待所有分组确认被接收的状态&#xff0c;这个状态会持续 2MSL&#xff08;Maximum Segment Lifetime&#xff09;的时间&#xff0c;以确保所有分组都被接收。在这段时间内&#xff0c;该连接不能被重用。MSL …