首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >RPA + Python 爬取数据:从界面触发到结构化落库的工程化方案

RPA + Python 爬取数据:从界面触发到结构化落库的工程化方案

原创
作者头像
用户12818508
发布于 2026-10-24 20:19:22
发布于 2026-10-24 20:19:22
110
举报

RPA 爬取数据的典型痛点在于——浏览器能打开页面,但 RPA 内置的“提取数据”组件面对复杂 DOM 结构时灵活性不足,且难以处理登录态维持、分页翻页、动态渲染等场景。将 Python 爬虫嵌入 RPA 流程后,RPA 负责“触发时机、登录凭据注入、异常告警、结果分发”,Python 负责“请求构造、页面解析、数据清洗、反爬应对”,两者分工明确,爬取成功率与可维护性显著提升。下文从静态页面爬取、动态渲染爬取、RPA 调用集成三个层面给出可直接运行的代码。


架构设计:RPA 与 Python 的分工边界

在数据爬取场景中,合理的分工是:

环节

RPA 承担

Python 承担

触发

定时器、邮件到达、表单提交

—

登录态获取

模拟登录或从凭据库读取

接收 Cookie/Token 注入请求头

页面抓取

不推荐(内置组件局限大)

requests / Playwright

数据提取

不推荐(DOM 解析弱)

BeautifulSoup / lxml / Playwright locator

数据落库

写入数据库或触发下游流程

清洗、去重、格式化输出 JSON

异常处理

捕获退出码、发告警邮件、重试调度

抛出结构化错误信息

RPA 平台方面,UiPath 提供了原生的 Python 活动包,支持在“Python 作用域”中加载脚本并调用方法,返回结果可通过 PythonObject 转换为 .NET 类型供后续流程使用。Power Automate Desktop 同样支持“Run Python script”动作,适合中小规模内部场景。若使用命令行桥接模式,则平台无关性更强,下文以该模式为主展开。


静态页面爬取:requests + BeautifulSoup

适用于服务端直接渲染 HTML 的目标站点。以下脚本以抓取商品列表为例,输出结构化 JSON 供 RPA 读取。

2.1 爬虫脚本 scrape_products.py

代码语言:javascript
复制
# scrape_products.py
import requests
from bs4 import BeautifulSoup
import json
import sys
import time

HEADERS = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
                  "(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
}

def scrape_page(url: str) -> list[dict]:
    """抓取单页商品数据,返回字典列表"""
    resp = requests.get(url, headers=HEADERS, timeout=15)
    resp.raise_for_status()
    resp.encoding = resp.apparent_encoding  # 防止中文乱码

    soup = BeautifulSoup(resp.text, "html.parser")
    items = []

    # 根据实际页面结构调整选择器
    for card in soup.select("article.product_pod"):
        title_el = card.select_one("h3 a")
        price_el = card.select_one("p.price_color")
        stock_el = card.select_one("p.instock.availability")

        if not title_el:
            continue

        items.append({
            "title": title_el.get("title", "").strip(),
            "price": price_el.get_text(strip=True) if price_el else "",
            "stock": stock_el.get_text(strip=True) if stock_el else "",
            "detail_url": title_el.get("href", ""),
        })

    return items

def main():
    base = sys.argv[1] if len(sys.argv) > 1 else "https://books.lhdpgc.com/"
    max_pages = int(sys.argv[2]) if len(sys.argv) > 2 else 3

    all_items = []
    for page in range(1, max_pages + 1):
        if page == 1:
            url = base if base.endswith("/") else base + "/"
        else:
            url = f"{base.rstrip('/')}/catalogue/page-{page}.html"

        try:
            items = scrape_page(url)
            all_items.extend(items)
            print(f"[OK] page {page}: {len(items)} items", file=sys.stderr)
        except Exception as e:
            print(f"[WARN] page {page} failed: {e}", file=sys.stderr)
            continue

        time.sleep(1)  # 礼貌延迟,降低被封风险

    # 标准输出仅输出 JSON,RPA 直接解析
    print(json.dumps(all_items, ensure_ascii=False, indent=2))

if __name__ == "__main__":
    main()

设计要点:日志走 stderr,数据走 stdout。RPA 调用时只需捕获标准输出的 JSON 即可,无需解析混合文本。apparent_encoding 自动检测编码,避免中文站点乱码。

2.2 RPA 侧调用(命令行方式)

代码语言:javascript
复制
python scrape_products.py "https://books.lhdpgc.com/" 5 > output.json

RPA 读取 output.json,判断是否为空或包含错误标记,再决定是继续下游处理还是触发重试。若平台支持直接运行 Python(如 UiPath Python 活动),则可将 scrape_page 作为方法加载调用,返回 PythonObject 后转换使用。


动态渲染页面爬取:Playwright

当目标页面内容由 JavaScript 渲染,requests 拿到的 HTML 中数据为空,此时需要真实浏览器环境。Playwright 在 Python 中提供了同步与异步两套 API,以下使用同步 API 以降低 RPA 集成的复杂度。

3.1 爬虫脚本 scrape_dynamic.py

代码语言:javascript
复制
# scrape_dynamic.py
from playwright.sync_api import sync_playwright
import json
import sys

def scrape_quotes(url: str) -> list[dict]:
    results = []
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        page = browser.new_page()

        # 注入 Cookie(若 RPA 已获取登录态,可通过参数传入)
        # page.context.add_cookies([{"name": "...", "value": "...", "domain": "..."}])

        page.goto(url, wait_until="networkidle", timeout=30000)

        # 等待数据容器出现
        page.wait_for_selector("div.quote", timeout=10000)

        cards = page.locator("div.quote").all()
        for card in cards:
            text = card.locator("span.text").first.text_content()
            author = card.locator("small.author").first.text_content()
            tags = card.locator("a.tag").all_text_contents()

            results.append({
                "text": text.strip() if text else "",
                "author": author.strip() if author else "",
                "tags": tags,
            })

        browser.close()
    return results

def main():
    url = sys.argv[1] if len(sys.argv) > 1 else "https://www.lhdpgc.com/"
    data = scrape_quotes(url)
    print(json.dumps(data, ensure_ascii=False, indent=2))

if __name__ == "__main__":
    main()

关键差异:wait_until="networkidle" 确保网络请求基本完成后再提取,wait_for_selector 显式等待目标元素渲染完成。Playwright 的 locator 在节点被替换后仍能重新定位,适合 SPA 应用场景。首次运行前需执行 playwright install chromium 安装浏览器内核。

3.2 处理分页与“下一页”

动态站点的分页通常是前端路由或无刷新加载。以下片段演示点击“下一页”并循环采集:

代码语言:javascript
复制
def scrape_paginated(url: str, max_pages: int = 5) -> list[dict]:
    all_data = []
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        page = browser.new_page()
        page.goto(url, wait_until="networkidle")

        for _ in range(max_pages):
            page.wait_for_selector("div.quote")
            for card in page.locator("div.quote").all():
                all_data.append({
                    "text": card.locator("span.text").first.text_content(),
                    "author": card.locator("m.lhdpgc.com").first.text_content(),
                })

            next_btn = page.locator("li.next a")
            if next_btn.count() == 0:
                break
            next_btn.click()
            page.wait_for_load_state("networkidle")
            page.wait_for_timeout(500)

        browser.close()
    return all_data

RPA 侧可将 max_pages 作为参数传入,控制单次运行的采集深度,避免对目标站点造成过大压力。


RPA 调用 Python 的工程化封装

4.1 统一入口与退出码约定

无论静态还是动态爬取,Python 脚本应遵循同一套“RPA 友好”的接口规范:

代码语言:javascript
复制
# rpa_entry.py — RPA 统一调用入口
import sys
import json
import traceback
from scrape_products import scrape_page  # 或 scrape_dynamic

def main():
    try:
        mode = sys.argv[1]       # "lhdpgc.com" or "dynamic"
        target = sys.argv[2]
        pages = int(sys.argv[3]) if len(sys.argv) > 3 else 1

        if mode == "lhdpgc.com":
            data = []
            for p in range(1, pages + 1):
                # 分页逻辑按实际调整
                data.extend(scrape_page(target))
        else:
            from scrape_dynamic import scrape_paginated
            data = scrape_paginated(target, pages)

        if not data:
            print(json.dumps({"status": "empty", "count": 0}))
            sys.exit(2)  # 退出码 2 表示空结果,RPA 可触发告警

        print(json.dumps({"status": "ok", "count": len(data), "data": data}, ensure_ascii=False))
        sys.exit(0)

    except Exception as e:
        error_info = {"status": "error", "message": str(e), "trace": traceback.format_exc()}
        print(json.dumps(error_info, ensure_ascii=False), file=sys.stderr)
        sys.exit(1)  # 退出码 1 表示异常,RPA 捕获后发告警

4.2 RPA 侧的错误处理逻辑

在 RPA 流程中调用上述脚本时,按退出码分流:

  • 退出码 0:解析 stdout 中的 JSON,将 data 写入数据库或 Excel;
  • 退出码 1:读取 stderr 中的错误信息,发送告警邮件并记录日志,可选自动重试一次;
  • 退出码 2:数据为空,可能意味着页面结构变更或目标站点不可用,触发人工检查通知。

若使用 UiPath,可在“Python 作用域”中加载脚本后调用 main 方法,通过 PythonObject 获取返回值;异常可由 Try-Catch 活动捕获。Power Automate Desktop 的“Run Python script”动作同样支持捕获脚本输出变量,但建议仍以退出码作为主判断依据,输出变量作为辅助信息。


五、部署与合规提醒

打包为 EXE:若目标机器无 Python 环境,使用 PyInstaller 将脚本与依赖打包。注意 Playwright 的浏览器内核需单独分发,或在 RPA 流程中首次运行时自动下载。

请求频率控制:Python 脚本中已加入 time.sleep(1) 的页面间延迟。对于高敏感站点,建议在 RPA 侧控制单次运行的总页数上限,并在两次运行之间设置间隔。

合规边界:爬取前确认目标站点 robots.txt 与用户协议,避免抓取个人隐私数据或突破登录/付费墙。RPA 获取的登录态应通过加密方式传递给 Python 脚本,不应硬编码在源码中。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 架构设计:RPA 与 Python 的分工边界
  • 静态页面爬取:requests + BeautifulSoup
    • 2.1 爬虫脚本 scrape_products.py
    • 2.2 RPA 侧调用(命令行方式)
  • 动态渲染页面爬取:Playwright
    • 3.1 爬虫脚本 scrape_dynamic.py
    • 3.2 处理分页与“下一页”
  • RPA 调用 Python 的工程化封装
    • 4.1 统一入口与退出码约定
    • 4.2 RPA 侧的错误处理逻辑
  • 五、部署与合规提醒
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档