首页
美图
服务
付费
树洞
云主机
推荐
邻居
支付
开发
书单
更多
我的足迹
罗盘时钟
圈小猫
工作打分
给我留言
本站统计
推荐
M商城
欣悦云店
txt阅读器
VPS监控
证书监控
网址导航
在线工具
Search
1
docker和docker-compose一键安装脚本
4,937 阅读
2
采用Prometheus+Grafana 监控H3C交换机状态
4,376 阅读
3
WooCommerce对接第三方支付插件开发
4,062 阅读
4
grafana的Dashboard面板添加阈值报警
2,800 阅读
5
docker下运行grafana和grafana Image Renderer
2,711 阅读
虚拟化
数据库
运维
基础知识
监控预警
数据展示
运维工具
web安全
系统服务
开发
python
php
java
shell
go
项目
博客
电商
工具
娱乐
综合
VPS相关
规范文档
知识总结
经验分享
读书笔记
关于
Search
标签搜索
django
python
运维工具
支付对接
电商平台
Joe主题
docker
wordpress
woocommerce
支付通道
zabbix
蓝鲸智云
运维
grafana
监控
运维知识
typecho
php
mysql
nginx
行云流水
累计撰写
324
篇文章
累计收到
355
条评论
首页
栏目
虚拟化
数据库
运维
基础知识
监控预警
数据展示
运维工具
web安全
系统服务
开发
python
php
java
shell
go
项目
博客
电商
工具
娱乐
综合
VPS相关
规范文档
知识总结
经验分享
读书笔记
关于
页面
美图
服务
树洞
云主机
邻居
支付
书单
给我留言
本站统计
推荐
M商城
txt阅读器
网址导航
搜索到
20
篇与
的结果
2024-10-24
基于Django的录音管理系统的开发总结
前言安卓手机默认打开了通话录音功能,几年下来积攒了上千条录音,一直懒得清理。最近写了一个管理系统,将所有录音文件导入。进行可视化分析,给自己几年打的所有电话生成一份报告。更直观的展示自己的通讯情况。{card-default label="统计" width="80%"}{/card-default}开发过程录音文件的管理通过django框架开发,主要功能点有通讯录管理、录音文件管理、录音文件转文字管理。转文字通过调用腾讯api完成,将结果保存到数据库,便于查询。可视化模块通过grafana直接读取mysql数据实现。模型类的设计模型类包括三种,Contact类、CallRecord类和RecordResult类。Contact类存储通讯录信息,包含名称和号码等class Contact(models.Model): number = models.CharField(max_length=15,verbose_name='电话号码') # 电话号码 name = models.CharField(blank=True,null=True,max_length=100,verbose_name='联系人') # 联系人姓名 # 新增的类型字段 TYPE_CHOICES = [ ('family', '亲朋'), ('work', '工作'), ('promotion', '推广'), ('taxi', '滴滴'), ('service', '客服'), ('delivery', '快递'), ] contact_type = models.CharField( max_length=10, choices=TYPE_CHOICES, verbose_name='类型', default='promotion', # 默认值为'亲朋' ) def __str__(self): return self.number class Meta: verbose_name = '通讯录' verbose_name_plural = '通讯录'CallRecord类用于存储音频文件、状态、音频转文字的任务信息等class CallRecord(models.Model): phone_number = models.ForeignKey(Contact, related_name='call_records', on_delete=models.CASCADE) # 电话号码外键 call_time = models.DateTimeField(verbose_name='时间') # 通话时间 recording_file = models.CharField(max_length=255, blank=True, null=True, verbose_name='文件名') # 录音文件名 notes = models.TextField(blank=True, null=True, verbose_name='备注') # 备注 task_id = models.CharField(max_length=255, blank=True, null=True, verbose_name='任务id') # 任务ID,可为空 # 状态字段的选择 STATUS_CHOICES = [ ('未处理', '未处理'), # Unprocessed ('处理中', '处理中'), # Processing ('已完成', '已完成'), # Completed ] status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='未处理', verbose_name='状态') # 状态,默认值为 '未处理' def __str__(self): return f"{self.phone_number.number} - {self.call_time}" # 返回通话记录的字符串表示 class Meta: verbose_name = '通话录音' # 该模型的单数名称 verbose_name_plural = '通话录音' # 该模型的复数名称RecordResult用于管理存储音频转文字的结果等信息class RecordResult(models.Model): call_record = models.OneToOneField(CallRecord, related_name='record_result', on_delete=models.CASCADE) # 与 CallRecord 的一对一关系 # 录音时长,单位为秒 duration = models.PositiveIntegerField(verbose_name='时长') # 时长,正整数 # 错误信息,可以为空 error_message = models.TextField(blank=True, null=True, verbose_name='错误') # 错误信息,可为空值 # 文本结果,可以为空 text_result = models.TextField(blank=True, null=True, verbose_name='全文') # 文本结果,可为空 # 文本大纲,可以为空 text_outline = models.TextField(blank=True, null=True, verbose_name='大纲') # 文本大纲,可为空 # 标签,可以为空 tags = models.CharField(max_length=255, blank=True, null=True, verbose_name='标签') # 标签,最多 255 字符,可以为空 # 备注,可以为空 notes = models.TextField(blank=True, null=True, verbose_name='备注') # 备注,可为空 def __str__(self): return f"{self.call_record.phone_number.number} - {self.duration}" class Meta: verbose_name = '通话文本' # 模型的单数名称 verbose_name_plural = '通话文本' # 模型的复数名称接口设计录音文件入库、文本结果处理等任务过程中用到的各种接口。# 防止重复入库的接口 class CheckRecordingFile(APIView): def post(self, request): # 获取file_name参数 file_name = request.data.get('file_name') if not file_name: return Response({"error": "file_name is required"}, status=status.HTTP_400_BAD_REQUEST) # 查询CallRecord中是否有这个file_name record_exists = CallRecord.objects.filter(recording_file=file_name).exists() # 根据查询结果返回True或False if record_exists: return Response({"exists": True}, status=status.HTTP_200_OK) else: return Response({"exists": False}, status=status.HTTP_200_OK) #录音在线播放用到的接口 class AudioList(APIView): def get(self, request): mediaList = [] # 获取URL查询字符串中的rid参数 rid = request.query_params.get('rid') cid = request.query_params.get('cid') if rid: mediaList = CallRecord.objects.filter(id=rid) if cid: contact = Contact.objects.get(id=cid) mediaList = CallRecord.objects.filter(phone_number=contact) arr = [] #倒序 for item in mediaList[::-1]: # 随机1-10专辑封面图片 sui_num = random.randint(1, 10) #构建 arr.append({ 'id': item.id, 'title': f"{item.record_result.id} - {item.phone_number.number} - {item.call_time}", 'singer': f"{item.phone_number.name}", 'songUrl': f"{settings.MEDIA_URL}{urllib.parse.quote(item.recording_file)}", 'imageUrl': '/static/images/' + str(sui_num) + '.png', }) return Response({'list': arr}, status=status.HTTP_201_CREATED)录音文件同步手机中的通讯录音会自动传输到家庭nfs,管理系统会单独启动一个循环任务去nfs拉取音频文件入库并创建音频转文字任务。import subprocess import time from datetime import datetime # 定义需要执行的命令 commands = [ "mkdir -p /tmp/lxnfs", "mount -t smbfs //189xxxxx805:zhixxxx6@192.168.1.150/7460088 /tmp/lxnfs", "cp -n /tmp/lxnfs/来自ADT-AN00的手机备份/文件夹备份/* /Users/xinei/project/audioman/data/files/ || true", "umount /tmp/lxnfs" ] # 定义一个函数来执行这些命令 def run_commands(): for command in commands: try: # 执行每条命令 subprocess.run(command, shell=True, check=True) print(f"执行成功: {command}") except subprocess.CalledProcessError as e: print(f"命令执行失败: {command}\n错误信息: {e}") # 主循环,每小时检查一次时间 while True: current_time = datetime.now() # 只在 20:00 到 24:00 之间执行命令 if current_time.hour >= 20 and current_time.hour < 23: print(f"当前时间: {current_time}. 在允许的时间范围内,执行命令。") run_commands() else: print(f"当前时间: {current_time}. 不在允许的时间范围内,跳过执行。") # 等待 1 小时再检查时间 time.sleep(3600)录音文件转文字录音文件写入数据库后,默认状态为待处理。另一个脚本会自动扫描未处理的记录,然后自动创建处理任务。# 监控指定目录 def monitor_directory(path): observer = None event_handler = MyEventHandler() try: while True: current_time = datetime.now() # 只在20:00到24:00之间执行监控 if current_time.hour >= 20 and current_time.hour < 24: if observer is None: # 只有在 observer 没有启动时才创建新的观察者 observer = Observer() observer.schedule(event_handler, path, recursive=False) observer.start() print(f"当前时间: {current_time}. 启动监控。") else: if observer is not None: observer.stop() observer.join() # 等待线程停止 observer = None # 将 observer 置为 None,以便后续创建新的实例 print(f"当前时间: {current_time}. 停止监控。") time.sleep(3600) # 每小时检查一次时间 time.sleep(600) # 每次监控状态保持10分钟,然后再循环检查 except KeyboardInterrupt: if observer is not None: observer.stop() observer.join() if __name__ == "__main__": directory_to_watch = "/files/" # 替换为你要监控的目录 monitor_directory(directory_to_watch)可视化过程可视化通过grafana实现。直接链接mysql数据库,通过sql查询数据并返回,具体页面如开头所示。完整项目代码获取【统计分析】基于Django开发的录音管理系统源码
2024年10月24日
9 阅读
0 评论
0 点赞
2024-09-27
爆火的轻量级AI证件照工具HivisionIDPhotos部署过程
前言HivisionIDPhotos是一款轻量级的AI证件照制作工具,它利用先进的图像处理技术和机器学习算法,简化了证件照的制作流程,确保生成的照片既符合官方证件的尺寸要求,又保持了高质量。无论是申请护照、驾照还是学生证,我们都可以用它来快速生成符合标准的证件照。{card-default label="制作界面" width="90%"}{/card-default}项目地址: HivisionIDPhotos部署采用docker启动,docker的安装参考以前的教程。部署很简单直接docker启动即可。基本环境docker和docker-compose一键安装脚本项目启动docker-compose up 项目文件:version: '3.8' services: hivision_idphotos: build: context: . dockerfile: Dockerfile image: linzeyi/hivision_idphotos command: python3 -u app.py --host 0.0.0.0 --port 7860 ports: - '3000:7860' hivision_idphotos_api: build: context: . dockerfile: Dockerfile image: linzeyi/hivision_idphotos command: python3 deploy_api.py ports: - '8080:8080'测试访问:http://ip:7860上传一张普通照片,然后即可制作。使用简单,制作质量也可以满足要求。{card-default label="制作效果" width="90%"}{/card-default}
2024年09月27日
34 阅读
0 评论
0 点赞
2024-09-02
支付网关DaxPay部署测试改造过程
前言DaxPay单商户是一套开源支付网关系统,已经对接支付宝、微信支付相关的接口。可以独立部署,提供接口供业务系统进行调用,不对原有系统产生影响, 适用于小型项目或简单收单的场景。本文记录部署测试记录。{card-default label="收款页面" width="90%"}{/card-default}核心技术栈JDK,1.8+,11版本可以正常使用,但17+版本暂不支持SpingBoot, 2.7xRedis, 5.x版本以上Mysql,5.7.X以上Vue,前端框架3.x项目部署过程数据库mysql,redis的部署过程略过。可以查阅一下往期的文章。本文主要记录项目代码部署的相关过程。所有项目代码的地址: 【支付源码】开源免费支付系统DaxPay源码数据库创建一个daxpay的数据实例。同时在后端项目中_config/sql目录下找到dax-pay.sql数据库脚本文件,导入daxpay数据库。# 建库 mysql -uroot -pmariadb@xxx -h 127.0.0.1 CREATE DATABASE `daxpay` DEFAULT CHARACTER SET utf8 COLLATE utf8_bin; create user 'dpuser'@'%' IDENTIFIED BY 'dpuserxxx'; grant all privileges on daxpay.* to 'dpuser'@'%'; flush privileges; # 导入demo数据 mysql -udpuser -pdpuserxxx -h 127.0.0.1 daxpay < ./_config/mysql/dax-pay.sqljava环境利用java和maven打包后端代码,在打包之前修改application.yml内的数据库连接信息。# java和maven的安装 yum install java-1.8.0-openjdk java-1.8.0-openjdk-devel wget https://downloads.apache.org/maven/maven-3/3.8.8/binaries/apache-maven-3.8.8-bin.tar.gz tar xvf apache-maven-3.8.8-bin.tar.gz mv apache-maven-3.8.8 /usr/local/maven # maven配置国内源 vim ~/.m2/settings.xml 内容见下面... # maven版本验证 java -version mvn -version # 项目打包 mvn -B clean package -Dmaven.test.skip=true -Dmaven.javadoc.skip=true -Dautoconfig.skipmaven国内源:<settings> <mirrors> <!-- 阿里云镜像 --> <mirror> <id>aliyun</id> <mirrorOf>*</mirrorOf> <url>https://maven.aliyun.com/repository/public</url> </mirror> <!-- 华为云镜像 --> <mirror> <id>hwcloud</id> <mirrorOf>*</mirrorOf> <url>https://mirrors.huaweicloud.com/repository/maven/</url> </mirror> <!-- 清华大学镜像 --> <mirror> <id>tsinghua</id> <mirrorOf>*</mirrorOf> <url>https://mirrors.tuna.tsinghua.edu.cn/maven/</url> </mirror> <!-- 中科大镜像 --> <mirror> <id>ustc</id> <mirrorOf>*</mirrorOf> <url>https://mirrors.ustc.edu.cn/maven/</url> </mirror> </mirrors> </settings>项目启动项目代码在docker内运行,使用docker-compose.yml管理。docker和docker-compose的安装见往期文章。构建docker镜像:隐藏内容,请前往内页查看详情构建命令:docker build -t dax-start:latest .docker-compose.yml内容隐藏内容,请前往内页查看详情前端代码因为项目采用前后端分离架构,前端代码需要单独构建。构建后将代码传输到服务器,然后用nginx服务器提供服务。# 安装node和pnpm环境,博主是mac系统: brew install node@16 pnpm@8 # 配置环境变量 echo 'export PATH="/opt/homebrew/opt/node@20/bin:$PATH"' >> ~/.zshrc echo 'export PATH="/opt/homebrew/opt/pnpm@8/bin:$PATH"' >> ~/.zshrc # 配置国内源 pnpm config set registry https://registry.npmmirror.com # 项目构建 pnpm install pnpm buildnginx服务服务有nginx代理静态资源,前端放caddy用于自动申请ssl证书。nginx配置:隐藏内容,请前往内页查看详情caddy2代理配置:隐藏内容,请前往内页查看详情至此所有配置完成。可以通过web登录后台,配置账号,支付通道等。{card-default label="管理后台" width="80%"}{/card-default}
2024年09月02日
33 阅读
0 评论
0 点赞
2024-08-21
新客户端IP一键过白功能开发与配置
前言部署了一个自己使用的web服务,不想对公网开放。最初用iptables对自己当前的电脑IP开放,禁止其他IP访问。每次路由器重启,或者在外出差,IP经常变动。需要登录服务器,新增新的IP。决定改变控制方式,利用nginx的IP白名单功能,同时用flask写了一个对公网开放的页面。当地址变动时,访问此页面。点击一键更新,就把最新的ip加入到nginx的白名单。同时重新加载nginx配置生效。{card-default label="ip更新页面" width="85%"}{/card-default}被控制服务需要进行ip访问控制,不对公网开放的nginx配置信息。default.conf配置用加载了ip白名单文件whitelist.conf# Appadmin server { listen 80; server_name 0.0.0.0; root /www/web/maccms_v10/; server_tokens off; #include none.conf; index index.php index.html index.htm; access_log /www/web_logs/wp_access.log wwwlogs; error_log /www/web_logs/wp_error.log notice; #auth_basic "请输入用户和密码"; # 验证时的提示信息 #auth_basic_user_file /etc/nginx/password; # 认证文件 location /{ include whitelist.conf; #默认位置路径为/etc/nginx/ 下, #如直接写include whitelist.conf,则只需要在/etc/nginx目录下创建whitelist.conf deny all; } location ~ \.php$ { fastcgi_pass php:9000; fastcgi_index index.php; include fcgi.conf; } #需要注意伪静态的配置 if (!-e $request_filename) { rewrite ^/index.php(.*)$ /index.php?s=$1 last; rewrite ^/api.php(.*)$ /api.php?s=$1 last; rewrite ^/adm0.php(.*)$ /adm0.php?s=$1 last; rewrite ^(.*)$ /index.php?s=$1 last; break; } location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 30d; } location ~ .*\.(js|css)?$ { expires 12h; } }whitelist.conf文件内存放需要开放的IP,文件内容:allow 101.31.158.153;控制服务文章开头的一键放通页面用flask框架实现, 单独部署app.py主要实现逻辑,有两个接口。一个接口提供页面,一个接口负责获取IP后更新,同时重新加载被控制服务的nginx配置隐藏内容,请前往内页查看详情index.html提供文章开头的一键更新功能的页面代码<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>IP 过白</title> <link rel="stylesheet" href="styles.css"> <!-- Link to external CSS file --> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <style> body { font-family: Arial, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; background-color: #f0f0f0; margin: 0; } .container { text-align: center; background-color: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); } h1 { color: #333; } #uploadBtn { background-color: #007bff; color: #fff; border: none; padding: 10px 20px; border-radius: 5px; cursor: pointer; font-size: 16px; transition: background-color 0.3s ease; } #uploadBtn:hover { background-color: #0056b3; } #uploadBtn:focus { outline: none; } </style> </head> <body> <div class="container"> <h1>更新此客户端IP</h1> <button id="uploadBtn">确认</button> </div> <script> $(document).ready(function() { $('#uploadBtn').click(function() { $.ajax({ type: 'POST', url: '/upload_ip', success: function(response) { if (response.status === 'success') { alert('IP 更新成功: ' + response.ip); ('Error: ' + response.message); } }, error: function() { alert('发生错误.'); } }); }); }); </script> </body> </html>服务启动控制服务通过systemd加载,配置文件为:/etc/systemd/system/ipallow.service。配置内容为[Unit] Description=IpAllow App [Service] User=root WorkingDirectory=/opt/ipallow ExecStart=/usr/local/bin/gunicorn -w 2 -b 0.0.0.0:801 app:app Restart=always [Install] WantedBy=multi-user.targetcaddy代理控制服务启动了服务器的801端口,通道caddy2代理到443,然后通过公网可访问。不用nginx代理的原因是控制服务会重启nginx,导致前端页面在等待返回结构时异常。b.test.xyz:443 { tls service@test.xyz encode gzip log { output file /logs/access.log } header / { Strict-Transport-Security "max-age=31536000;includeSubdomains;preload" } #访问认证 basicauth / { cms $2a$14$bNLxxxxxxxxxxxxxxxxxxxxxxGAbzyOUyoBn1rjfpN/O } ## HTTP 代理配置 reverse_proxy http://192.168.0.203:801 { header_up X-Real-IP {http.request.remote.host} header_up X-Forwarded-For {http.request.remote.host} header_up X-Forwarded-Port {http.request.port} header_up X-Forwarded-Proto {http.request.scheme} } }caddy认证密码生产caddy的认证密码caddy hash-password --plaintext 'cmsxxxx'
2024年08月21日
40 阅读
0 评论
0 点赞
2024-07-31
扫码点餐系统管理后台界面
前言前几天搭建部署了扫码点餐平台,继续介绍平台的功能。本文主要分享管理员后台的相关界面首页登录系统后首先看到的是首页仪表盘,包含一些系统信息。{card-default label="首页仪表盘" width="85%"}{/card-default}设置设置包括站点设置、登录注册、功能设置、分佣设置、消息提醒、友情链接等{card-default label="设置界面" width="85%"}{/card-default}
2024年07月31日
416 阅读
0 评论
0 点赞
2024-07-28
餐厅扫码点餐平台搭建部署过程
前言扫码点餐越来越流行,最近接了一个新的项目。为某餐厅上一套扫码点餐系统。记录整个部署过程。{card-default label="系统介绍" width="80%"}{/card-default}{card-describe title="源码介绍"}本框架是基于ThinkPHP的多应用模式所开发的,采用MVC的设计模式,每个模块分为三层(模型M、视图V、控制器C)。默认应用模块:common、admin、agent、user、index、applet、api、store{/card-describe}环境要求,均采用docker方式启动:PHP版本 >= 7.4 (推荐PHP7.4版本)MySql版本 >= 5.6 (需支持innodb引擎)Apache版本 >= 2.4以上 或 Nginx >= 1.10(推荐使用宝塔等集成环境)其它:服务器支持https,必须安装SSL证书,否则会影响接口的通信。部署过程详细部署过程,有专门的文档。 hemaPHP ,本文只记录部署过程中遇到的问题。构建php的docker镜像docker的官网被封了,需要搭建自己的私有源镜像。docker login --username=xwzy1130 registry.cn-hangzhou.aliyuncs.com #推送 docker tag 8933d3e7e14b registry.cn-hangzhou.aliyuncs.com/mybud/php74:lastest docker push registry.cn-hangzhou.aliyuncs.com/mybud/php74:lastest # 引用 docker pull registry.cn-hangzhou.aliyuncs.com/mybud/php74:lastestnginx配置nginx/services/nginx/conf/conf.d/hema_saas.confserver { listen 802; server_name 0.0.0.0; root /www/web/hema_saas/public; index index.html index.htm index.php; charset utf-8; access_log /www/web_logs/dcb.log wwwlogs; error_log /www/web_logs/dcb.err notice; server_tokens off; client_max_body_size 50m; error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } location / { if (!-e $request_filename) { rewrite ^(.*)$ /index.php?s=/$1 last; break; } } location ~ \.php$ { fastcgi_pass 10.0.16.8:9000; fastcgi_index index.php; include fcgi.conf; fastcgi_buffers 8 4K; fastcgi_buffer_size 4K; } location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 30d; } location ~ .*\.(js|css)?$ { expires 12h; } }
2024年07月28日
126 阅读
0 评论
0 点赞
2024-02-01
零基础利用chatgpt两天手写一个go客户端程序
前言pc客户端程序的编写一直是我从未涉足过的领域。最近有了需求,需要写一个pc客户端运行的程序。功能要求简单,实现文件上传即可。不过不想麻烦,想着费一边事。就可以跨平台,运行。直接问chatgpt采用什么方案。最终选择了go语言,编译出来的执行文件很小,还支持交叉编译。{card-default label="程序界面" width="75%"}{/card-default}环境配置作者原先还没有go环境,先安装好go环境。然后问chatgpt运行helloworld示例程序。{card-default label="helloword" width="75%"}{/card-default}程序开发生成带界面的helloword直接问chatgpt。{card-default label="界面hello" width="75%"}{/card-default}功能函数还是将想法直接和chatgpt交流,把chatgpt的返回,复制到代码中。调试,运行。直到整个代码的完成。最终的代码一共308行。几乎全部是chatgpt返回。中间解决了几个代码问题。有时候chatgpt的返回,总是不正确,需要用搜索引擎去寻找答案。{card-default label="代码行数" width="75%"}{/card-default}
2024年02月01日
338 阅读
0 评论
0 点赞
2023-03-16
直播推流管理系统prtmp的开发过程总结
去年通过docker部署rtmp服务并进行网络压力测试,今年我们的业务终于用到了直播流服务。自己写了一个小系统用来从上游拉取直播流并分发到阿里云或者腾讯的直播服务。然后供小程序调用。特此记录整个配置过程。
2023年03月16日
331 阅读
0 评论
0 点赞
2023-02-21
通过Django管理周期性任务-feapder爬虫
一开始感兴趣的信息比较少,直接用crontab启动就满足要求了。后台爬虫越来越多,有的爬虫早就失效了,也没发现。只能花时间自己搞一个简易版管理系统。
2023年02月21日
587 阅读
0 评论
0 点赞
2023-01-09
爬虫管理系统FEAPLAT部署与使用
去年用feapder写了几个小爬虫,定时收集自己感兴趣的数据,运行的挺稳定的。官方的 feaplat爬虫管理系统,新版本好像可以免费20个采集任务,够自己用了。
2023年01月09日
621 阅读
0 评论
0 点赞
1
2