前言
最近公司有个需求是抓取公司员工在各大平台的粉丝数。本文将介绍通过RPA工具如何实现这一需求,以及如何通过python自动化每日执行该服务
每日一想
- rpa影刀工具如何使用?如何搭建各个平台的流程并且能够根据对应账号连接拉起对应的抓取流程?
- 怎么获取要抓取的账号数据?怎么把抓到的数据成功的放到数据库中?
- python自动化启动怎么实现?
- 后续优化?
那么,带着这几个问题,我们一起往下走,一探究竟~~
rpa工具
具体介绍不多做赘述,可以看下这篇文章
搭建某音的流程
抖音的抓取流程是通过一个开源的python工具来实现的,大家可以自己拉下来看一下,里面集成了各种获取数据的模式,webAPI,终端等,也可以抓取任何数据
搭建某书的流程
某书是ssr渲染的,这里处理起来比较麻烦,需要借助eval函数'
某站和某手的搭建流程类似,这里就不做过多赘述啦~~
主流程
影刀中可以通过指令来发送钉钉群通知,这样可以方便我们及时了解数据抓取情况
获取账号数据以及数据落库
相信大家在看到上面的主流程时,可以看到有一条mysql的查询命令,没错,就是通过影刀中该指令创建数据库连接,然后执行查询命令,获取到想要的数据。
这样做的好处是,不需要线下去拆表,还有更新表,如果账号数据有更新的话,直接更新数据库即可。
数据落库,是通过本地启动一个node服务,通过webAPI模式来调用,把需要的参数传进来,在通过执行mysql命令插入到数据库中,下面是部分代码
js
export async function uploadMarketing(params) {
const { type } = params;
// type === 1 个人账号 2 官方账号
try {
if(type == 1) {
const { likeCnt, fansCnt, accountId, platform, staffCode } = params;
const statDate = datetime.format(new Date(), 'YYYY-MM-DD');
const outside = 'personal_account_stat'; // 指定操作哪张表
const sqlStr = `INSERT INTO ${outside} (like_cnt, fans_cnt, account_id, platform, staff_code, stat_date) VALUES (?, ?, ?, ?, ?, ?)`
db.query(sqlStr, [likeCnt, fansCnt, accountId, platform, staffCode, statDate], (err, result) => {
if(err) return;
if(result.affectedRows === 1) {
sendMarkdownMessage({ title: `个人账号-${platform}数据插入成功`, text: `账号ID-${accountId} 工号-${staffCode}` });
}
})
} else {
const { likeCnt, fansCnt, accountId, platform, accountName } = params;
const statDate = datetime.format(new Date(), 'YYYY-MM-DD');
const outside = 'offical_account_stat' // 指定操作哪张表
const sqlStr = `INSERT INTO ${outside} (like_cnt, fans_cnt, account_id, platform, account_name, stat_date) VALUES (?, ?, ?, ?, ?, ?)`
db.query(sqlStr, [likeCnt, fansCnt, accountId, platform, accountName, statDate], (err, result) => {
if(err) return;
if(result.affectedRows === 1) {
sendMarkdownMessage({ title: `官方账号-${platform}数据插入成功`, text: `账号名称-${accountName}` });
}
})
}
} catch (error) {
sendMarkdownMessage({ title: '上传失败', text: `账号ID-${accountId}上传失败` });
}
}
python 自动化启动
所谓的自动化启动,我理解的就是加一个定时任务,通过定时任务,触发某个文件的更新,然后使用影刀的触发器来监听文件的更新,从而达到自动化启动的功能。下面是具体实现。
-
获取影刀进程
pythondef wait_for_process(process_name, timeout=None): start_time = time.time() while True: for process in psutil.process_iter(['pid', 'name']): try: process_info = process.info if process_info['name'] == process_name: return process_info['pid'] except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): pass if timeout is not None and time.time() - start_time > timeout: return None time.sleep(1)
通过python的
psutil
库来获取系统进程,(该库可以获取系统的硬盘,网络,进程等信息) -
启动node服务
jsdef open_sql_server(): project_path = r"" if os.name == 'nt': # windows系统 New Technology project_path = project_path.replace('/', '\\') subprocess.run('start cmd /k "cd /d {} && npm run dev"'.format(project_path), shell=True)
通过python的
subprocess
库来启动服务,注意要加shell=true,表示通过shell命令来启动 -
写入文件
jsfile_path = r"" def append_time_to_file(file_path): try: open_sql_server() time.sleep(5) # 等待五秒,确保服务能够启动 current_time = time.strftime("%Y-%m-%d %H:%M:%S") new_content = f"触发时间:{current_time}" with open(file_path, "a", encoding='utf-8') as file: file.write("\n" + new_content) print("内容已追加,当前时间为:", current_time) except Exception as e: print("追加内容时出现错误:", e)
需要在指定位置新建文件,当服务成功启动时,会在该文件中新增一条信息,方便查看日志
-
定时任务
jsdef my_task(): print("任务运行中...") if os.path.exists(file_path): append_time_to_file(file_path) else: print("文件不存在:", file_path) my_task(); schedule.every().day.at("04:00").do(my_task) # 每天四点启动 def run_scheduler(): while True: schedule.run_pending() time.sleep(1) run_scheduler()
通过python的
schedule
库来实现定时任务,并可以指定时间点启动 -
影刀监听文件更新
应用选择自己需要执行的应用,注意需要把应用发版。
监控文件填在上面新建的文件路径即可,监控事件选更新。
后续优化
- 目前python中,无法关闭终端进程,这样会造成一直重复打开终端,尝试多种方法无果...
- 目前自动化启动是在本地电脑中,这样如果电脑关机,该定时任务无法启动,所以后续会考虑放到服务器上。
- IP被限制问题有待优化,如果抓取数量太大,会有封号的风险。