找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

3687

积分

0

好友

507

主题
发表于 2026-2-11 10:38:07 | 查看: 31| 回复: 0

最近一位律师朋友向我吐槽,即便在AI和数字化普及的今天,很多垂直行业的数据采集依然严重依赖人工。专利信息就是典型例子:律师或分析师需要分别访问美国专利商标局(USPTO)、谷歌专利(Google Patents)等各国网站,手动查询、记录,最后再汇总到Excel表格中。这个过程重复、琐碎,面对的是上百个国家、上亿条的数据量,效率极低。

专利搜索结果示例

一个很自然的疑问是:为什么没有一个整合平台来统一采集和处理这些公开的专利数据?这背后其实存在三大技术难点。首先,数据源极其分散,且格式各异,有纯文本、数字表格、动态页面等,难以用统一方式高效检索。其次,各大专利数据库都设有严密的反爬虫机制,例如JavaScript动态渲染、CAPTCHA验证码、IP封锁以及浏览器指纹检测,极大地增加了自动化采集的难度。最后,数据采集过程必须保证合规与安全,既不能干扰目标网站的正常运行,也要遵循不同国家或地区的法规要求。

因此,我决定动手开发一个工具,尝试解决这个问题。我的方案是使用Python结合亮数据(Bright Data)的网页解锁(Web Unlocker)API来构建一个桌面GUI系统。该系统支持通过专利号或关键词检索多个专利源的信息,并将结果统一展示,同时提供一键导出为Excel的功能。

专利数据采集系统界面

技术选型与思路

核心工具链选择了requestspandastkinterrequests库负责通过亮数据API发送请求,直接绕过复杂的反爬机制,并确保请求的合规性。pandas则用于处理采集到的数据,进行格式转换和清洗。而tkinter作为Python的标准GUI库,足够轻量,非常适合构建这类功能明确的小型桌面应用。

整个项目的关键点在于如何稳定、合规地获取网页数据。这正是亮数据网页解锁API的价值所在。它将应对各类反爬技术(如代理IP池、验证码破解、浏览器指纹管理等)的复杂逻辑封装成了一个简单的API接口。开发者只需调用这个API,就能像真实用户一样访问目标页面,从而将精力集中于业务逻辑与数据分析,而非与反爬策略“斗智斗勇”。

亮数据Web Unlocker架构流程图

需要强调的是,本文分享的GUI系统仅为个人技术研究的Demo版本,不用于任何商业用途。

准备工作与环境配置

  1. Python环境:建议使用Python 3.8或更高版本。通过pip安装以下必要的第三方库(tkinter通常随Python安装,无需额外安装)。

    • requests: 用于发送HTTP请求,与亮数据API交互。
    • beautifulsoup4: 用于解析返回的HTML内容。
    • pandas: 用于数据处理和Excel导出。
    • openpyxl: pandas导出Excel所需的引擎。

    安装命令:

    pip install requests beautifulsoup4 pandas openpyxl
  2. 获取亮数据API密钥:访问亮数据官网注册账号。登录控制台后,创建一个“Web Unlocker”代理基础设施项目。创建成功后,你将获得一个专属的API KeyZone名称,这是调用服务的凭证,请妥善保存。

亮数据代理基础设施配置界面

控制台会提供各语言的调用示例代码,这可以作为我们编写采集模块的绝佳起点。

亮数据API调用示例代码

注意:免费试用账号通常有流量或频率限制,正式使用需根据需求购买相应套餐。

  1. 项目结构规划:创建一个清晰的项目目录,例如patent_search_system,并在其中创建以下模块文件:
    • main.py: 程序主入口,启动GUI。
    • patent_scraper.py: 封装亮数据API请求的核心模块。
    • parser.py: 网页数据解析模块,针对不同数据源定制。
    • gui_interface.py: GUI界面实现模块。
    • excel_exporter.py: 数据导出模块。
    • config.py: 配置文件,存放API密钥等敏感信息(注意不要提交到版本控制)。

系统设计与核心实现

本次Demo主要对接两个数据源:USPTO和Google Patents。为了系统具有良好的扩展性,我们采用了抽象工厂模式。为每个数据源实现统一的接口,包括:

  • detect_query_type(): 自动判断输入是专利号还是关键词。
  • search(): 执行检索并解析返回的专利数据。
  • batch_search(): 处理批量查询任务。

这样的设计使得未来新增数据源(如EPO、WIPO)时,只需添加新的解析类,而无需修改主程序逻辑。

为了实现跨数据源的统一展示,我们定义了一个标准的专利数据结构:

字段名 说明 数据类型
patent_number 专利号 字符串
title 专利标题 字符串
country 国别(如 CN, US, EP) 字符串
application_date 申请日期 日期字符串
inventors 发明人列表 列表
technology_field 技术领域 字符串
source 数据来源(如 “USPTO”) 字符串
query_type 查询类型(“fuzzy”/“exact”) 字符串

所有数据源的解析结果都将被转换为此格式。

1. 封装Web Unlocker调用

这是数据采集的基石。我们创建一个PatentScraper类,封装与亮数据API的交互。

# patent_scraper.py
import requests
from typing import Literal, Optional
from config import BRIGHT_DATA_API_KEY, UNLOCKER_ZONE, UNLOCKER_ENDPOINT

class PatentScraper:
    def __init__(self, api_key: str = BRIGHT_DATA_API_KEY, zone: str = UNLOCKER_ZONE):
        self.api_key = api_key
        self.zone = zone
        self.endpoint = UNLOCKER_ENDPOINT
        self.headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json",
        }

    def fetch(self,
              url: str,
              method: Literal["GET", "POST"] = "GET",
              body: Optional[str] = None,) -> str:
        payload = {
            "zone": self.zone,
            "url": url,
            "format": "raw", # 返回原始 HTML
            "method": method,
        }
        if body:
            payload["body"] = body
        response = requests.post(self.endpoint, headers=self.headers, json=payload)
        return response.text

2. 实现数据解析器

针对不同的数据源,编写相应的解析函数。以Google Patents为例:

# parser.py (部分代码)
from bs4 import BeautifulSoup
from typing import Dict, Any, List

def parse_google_patent(html: str) -> Dict[str, Any]:
    soup = BeautifulSoup(html, "html.parser")
    result = {}

    # 专利号 & 国别
    patent_number = None
    country = None
    title_tag = soup.find("meta", {"itemprop": "publicationNumber"})
    if title_tag and title_tag.get("content"):
        pub = title_tag["content"] # 例如 "US1234567A"
        patent_number = pub
        country = pub[:2] # 简单取前两位作为国别代码
    result['patent_number'] = patent_number
    result['country'] = country

    # 申请日
    application_date = None
    app_date_meta = soup.find("meta", {"itemprop": "filingDate"})
    if app_date_meta and app_date_meta.get("content"):
        application_date = app_date_meta["content"]
    result['application_date'] = application_date

    # 发明人
    inventors: List[str] = []
    for inv in soup.select("[itemprop='inventor']"):
        name_tag = inv.find(attrs={"itemprop": "name"})
        if name_tag:
            inventors.append(name_tag.get_text(strip=True))
    result['inventors'] = list(dict.fromkeys(inventors)) # 去重

    # ... 解析标题、技术领域等其他字段
    result['source'] = 'Google Patents'
    return result

3. 开发数据导出功能

利用pandas,可以非常轻松地将结果列表导出为Excel文件。

# excel_exporter.py
import pandas as pd
from typing import List, Dict
import os

def export_to_excel(results: List[Dict], filename: str):
    """将专利搜索结果导出到Excel文件"""
    if not results:
        raise ValueError("没有数据可导出")

    # 准备DataFrame
    df_data = []
    for idx, result in enumerate(results, 1):
        row = {
            '序号': idx,
            '专利号': result.get('patent_number', ''),
            '标题': result.get('title', ''),
            '国别': result.get('country', ''),
            '申请日期': result.get('application_date', ''),
            '发明人': ', '.join(result.get('inventors', [])),
            '技术领域': result.get('technology_field', ''),
            '来源': result.get('source', ''),
            '查询类型': result.get('query_type', ''),
        }
        df_data.append(row)

    df = pd.DataFrame(df_data)
    # 确保目录存在
    os.makedirs(os.path.dirname(os.path.abspath(filename)), exist_ok=True)
    df.to_excel(filename, index=False)
    print(f"数据已成功导出至: {filename}")

4. 构建GUI交互界面

最后,使用tkinter将上述模块整合成一个可视化的桌面应用。

# gui_interface.py (部分代码)
import tkinter as tk
from tkinter import ttk, scrolledtext, messagebox, filedialog
import threading
from patent_scraper import MultiSourcePatentEngine # 假设有一个整合了多个源的引擎类

class PatentSearchGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("专利数据采集系统")
        self.root.geometry("1000x700")

        # 创建专利搜索引擎实例
        self.engine = MultiSourcePatentEngine()
        self.results = []

        self.setup_ui()

    def setup_ui(self):
        # 创建查询设置、输入框、按钮、结果表格、日志区域等控件
        # ... (详细的UI布局代码)
        pass

    def on_search(self):
        # 绑定搜索按钮事件,在新线程中执行搜索,避免GUI卡顿
        keyword = self.entry.get()
        if not keyword:
            messagebox.showwarning("提示", "请输入查询关键词或专利号!")
            return

        def search_task():
            self.log("开始搜索...")
            try:
                results = self.engine.search(keyword)
                self.results = results
                # 更新结果表格
                self.update_result_table(results)
                self.log(f"搜索完成,共找到 {len(results)} 条结果。")
            except Exception as e:
                self.log(f"搜索出错: {e}")
                messagebox.showerror("错误", f"搜索过程中发生错误: {e}")

        threading.Thread(target=search_task, daemon=True).start()

    def on_export(self):
        # 绑定导出按钮事件
        if not self.results:
            messagebox.showinfo("提示", "没有数据可导出")
            return
        filename = filedialog.asksaveasfilename(defaultextension=".xlsx",
                                                 filetypes=[("Excel文件", "*.xlsx")])
        if filename:
            try:
                export_to_excel(self.results, filename)
                messagebox.showinfo("成功", f"数据已导出至:\n{filename}")
            except Exception as e:
                messagebox.showerror("导出失败", str(e))
    # ... 其他方法

运行与效果展示

完成所有模块开发后,在main.py中启动GUI程序。

# main.py
from gui_interface import PatentSearchGUI
import tkinter as tk

if __name__ == "__main__":
    root = tk.Tk()
    app = PatentSearchGUI(root)
    root.mainloop()

运行main.py,即可打开我们构建的专利数据采集系统。

系统初始界面

在查询输入框中输入技术关键词(例如“AI”),选择数据源和查询类型,点击“开始搜索”。系统会通过亮数据API并行查询多个专利数据库,并将解析、清洗后的结果统一展示在表格中。

关键词“AI”的模糊查询结果

点击“导出Excel”,即可将所有搜索结果保存为结构清晰的电子表格,供后续分析使用。

总结

通过这个项目,我们成功利用Python和亮数据的Web Unlocker API,构建了一个能够自动、合规地采集多源专利数据,并具备友好图形界面的工具。它虽然是一个简化版本,但清晰地展示了如何将分散的数据源、复杂的反爬机制与最终的用户需求连接起来,形成一个可用的数据采集解决方案。这不仅是技术上的实践,也为解决类似的数据整合难题提供了一种可行的思路。

如果你想了解更多关于Python自动化或网络数据采集的实战技巧,欢迎来云栈社区交流探讨。




上一篇:C++面试五大易错点解析:智能指针、移动语义与虚函数表详解
下一篇:发实物还是发现金?公司福利背后的成本优势与心理溢价
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-2-23 11:43 , Processed in 0.903035 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表