当前位置:首页>python>【全网独一份·超级干货】Python自动化+代理抓包:批量采集公众号文章阅读、点赞、转发、收藏等互动数据

【全网独一份·超级干货】Python自动化+代理抓包:批量采集公众号文章阅读、点赞、转发、收藏等互动数据

  • 2026-09-20 17:43:04
【全网独一份·超级干货】Python自动化+代理抓包:批量采集公众号文章阅读、点赞、转发、收藏等互动数据

“带你横跨办公自动化的数据江海”

@摸鱼

闻道有先后,术业有专攻。

各位大佬好!

~我依旧是你们的老朋友摸鱼~

♥ 1

在职场摸爬滚打的这十多年里,我用Python悄悄干了不少“正事”——不知不觉攒下了一整套办公自动化的实用项目技巧。去年10月初创立了公众号 「码海听潮」 ,初衷很简单:把重复的劳动交给代码,把摸鱼的时间留给生活。

目前已经吭哧吭哧更新了近90篇原创文章,每一篇都是实操干货,不讲虚的,只聊怎么用代码真正解放双手,帮大家早点下班、准点摸鱼

♥ 2

♥ 3

好叻,多了不说,少了不唠,咱直接上干货。

办公需求场景

从崩溃到优雅的进化

有一个微信公众号,里面有多篇已发布文章的阅读、点赞、评论、在看等互动数据。现在的需求是批量把这些文章的数据按照'公众号', '用户名', '文章标题', '作者', '发布时间', '原创', '封面图片', '摘要', '文章短链接', '文章长链接', '阅读数', '在看或推荐数', '转发数', '点赞数', '评论数', '收藏数'等字段进行统计记录,并保存为Excel表,要是这种类似的需求你的Big Boss安排你去完成,请问阁下该如何应对?

办公痛点分析

01

痛点一:效率低下,耗时耗力

    • 假设一个公众号每周发布7篇文章,一个月就是28篇。按照人工操作,每篇文章需要打开后台、定位到该文、记录十多个字段的数据,整个过程至少需要花费几个小时。如果有多个公众号需要维护,工作量会成倍增长

    02

    痛点二:手工录入,极易出错

      • 所有数据都需要人工填写到Excel表中,阅读量、点赞数、转发数这些数字很容易看串行或输错。而且一篇篇文章录入,非常容易遗漏某篇文章,事后也很难核对哪里出了差错。一旦出错,复盘报告的依据就不准确了。

      由此可见若下载成百上千个微信公众号话整个操作流程繁琐且耗时,高频次的鼠标点击和键盘输入使操作者手指疲劳,堪称"键盘敲冒烟"式的体力劳动,加上人工疲劳操作极易导致遗漏文件夹。于是乎这时候,按以往的 “解题套路”,Python 的专属 BGM 该响起来了 ——go~ go~ go~,救苦救难的大救星这不就来了!!

      @摸鱼

      问题拆解思路

      1.登录微信公众平台,抓取符合条件的公众号文章→

      2.启动代理监控进行实时抓包→

      3.在微信中自动打开文章,当文章页面加载时,代理实时捕获并解析数据→

      4.对代理抓包获取到的数据保存到excel表里

      下面,我就用python代码让各位大佬见识一下,什么叫"传统文化遇上赛博效率"(仅展示部分代码,非完整代码,需完整代码看文章末尾说明~)

      import sysfrom datetime import datetimefrom PyQt6.QtWidgets import (    QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,    QLabel, QLineEdit, QPushButton, QTextEdit, QGroupBox, QGridLayout,    QProgressBar, QSplitter, QMessageBox, QDateTimeEdit, QTabWidget,     QTableWidget, QTableWidgetItem, QHeaderView, QFileDialog)from PyQt6.QtCore import Qt, QThread, pyqtSignal, QDateTimefrom PyQt6.QtGui import QFont, QTextCursorclass WorkThread(QThread):    """工作线程 - 用于执行耗时操作"""    log_signal = pyqtSignal(str)    progress_signal = pyqtSignal(int)    finished_signal = pyqtSignal(bool, str)    result_signal = pyqtSignal(dict)    def __init__(self, config):        super().__init__()        self.config = config    def run(self):        """执行任务(此处调用原有功能)"""        passclass LogTextEdit(QTextEdit):    """自定义日志文本框"""    def __init__(self, parent=None):        super().__init__(parent)        self.setReadOnly(True)        self.setFont(QFont("Consolas", 10))        self.setStyleSheet("""            QTextEdit {                background-color: #1e1e1e;                color: #d4d4d4;                border: 1px solid #3c3c3c;                border-radius: 5px;                padding: 5px;            }        """)    def append_log(self, message):        """添加日志消息"""        self.append(message)        cursor = self.textCursor()        cursor.movePosition(QTextCursor.MoveOperation.End)        self.setTextCursor(cursor)class MainWindow(QMainWindow):    """主窗口"""    def __init__(self):        super().__init__()        self.work_thread = None        self.init_ui()    def init_ui(self):        """初始化UI"""        self.setWindowTitle("微信公众号文章数据采集工具(欢迎关注微信公众号:码海听潮)")        self.setMinimumSize(1200, 800)        # 设置窗口样式        self.setStyleSheet("""            QMainWindow {                background-color: #f5f5f5;            }            QGroupBox {                font-weight: bold;                border: 1px solid #cccccc;                border-radius: 5px;                margin-top: 10px;                padding-top: 10px;                background-color: white;            }            QGroupBox::title {                subcontrol-origin: margin;                left: 10px;                padding: 0 5px 0 5px;            }            QLabel {                color: #333333;            }            QLineEdit, QDateTimeEdit {                padding: 5px;                border: 1px solid #cccccc;                border-radius: 3px;                background-color: white;            }            QLineEdit:focus, QDateTimeEdit:focus {                border-color: #0078d4;            }            QPushButton {                background-color: #0078d4;                color: white;                border: none;                border-radius: 3px;                padding: 8px 15px;                font-weight: bold;            }            QPushButton:hover {                background-color: #106ebe;            }            QPushButton:pressed {                background-color: #005a9e;            }            QPushButton:disabled {                background-color: #cccccc;                color: #666666;            }            QProgressBar {                border: 1px solid #cccccc;                border-radius: 3px;                text-align: center;                background-color: white;            }            QProgressBar::chunk {                background-color: #0078d4;                border-radius: 3px;            }            QTabWidget::pane {                border: 1px solid #cccccc;                border-radius: 5px;                background-color: white;            }            QTabBar::tab {                background-color: #f0f0f0;                padding: 8px 20px;                margin-right: 2px;                border-top-left-radius: 4px;                border-top-right-radius: 4px;            }            QTabBar::tab:selected {                background-color: white;                border-bottom: 2px solid #0078d4;            }            QTableWidget {                border: none;                gridline-color: #e0e0e0;            }            QTableWidget::item {                padding: 5px;            }            QHeaderView::section {                background-color: #f0f0f0;                padding: 5px;                border: 1px solid #e0e0e0;                font-weight: bold;            }        """)        # 中央部件        central_widget = QWidget()        self.setCentralWidget(central_widget)        # 主布局        main_layout = QVBoxLayout(central_widget)        main_layout.setSpacing(10)        main_layout.setContentsMargins(10, 10, 10, 10)        # 创建分割器        splitter = QSplitter(Qt.Orientation.Vertical)        # 顶部配置区域        config_widget = self.create_config_widget()        splitter.addWidget(config_widget)        # 底部日志区域        log_widget = self.create_log_widget()        splitter.addWidget(log_widget)        # 设置分割比例        splitter.setSizes([400, 400])        main_layout.addWidget(splitter)        # 底部按钮区域(居中显示)        button_layout = QHBoxLayout()        button_layout.addStretch()  # 左侧弹簧        self.start_btn = QPushButton("开始采集")        self.start_btn.clicked.connect(self.start_task)        self.start_btn.setMinimumWidth(120)        self.stop_btn = QPushButton("停止")        self.stop_btn.clicked.connect(self.stop_task)        self.stop_btn.setEnabled(False)        self.stop_btn.setMinimumWidth(120)        self.stop_btn.setStyleSheet("""            QPushButton {                background-color: #d9534f;            }            QPushButton:hover {                background-color: #c9302c;            }        """)        button_layout.addWidget(self.start_btn)        button_layout.addSpacing(20)  # 按钮间距        button_layout.addWidget(self.stop_btn)        button_layout.addStretch()  # 右侧弹簧        main_layout.addLayout(button_layout)    def create_config_widget(self):        """创建配置区域"""        widget = QWidget()        layout = QVBoxLayout(widget)        # 基本配置组        basic_group = QGroupBox("基本配置")        basic_layout = QGridLayout(basic_group)        basic_layout.setSpacing(10)        # 公众号名称        basic_layout.addWidget(QLabel("公众号名称:"), 0, 0)        self.wechat_name_edit = QLineEdit("码海听潮")        self.wechat_name_edit.setPlaceholderText("请输入公众号名称")        basic_layout.addWidget(self.wechat_name_edit, 0, 1)        # 代理配置        basic_layout.addWidget(QLabel("代理地址:"), 1, 0)        proxy_layout = QHBoxLayout()        self.proxy_host_edit = QLineEdit("127.0.0.1")        self.proxy_host_edit.setMaximumWidth(150)        proxy_layout.addWidget(self.proxy_host_edit)        proxy_layout.addWidget(QLabel(":"))        self.proxy_port_edit = QLineEdit("8888")        self.proxy_port_edit.setMaximumWidth(80)        proxy_layout.addWidget(self.proxy_port_edit)        proxy_layout.addStretch()        basic_layout.addLayout(proxy_layout, 1, 1)        # 日期范围        basic_layout.addWidget(QLabel("开始日期:"), 2, 0)        self.start_date_edit = QDateTimeEdit()        self.start_date_edit.setCalendarPopup(True)        self.start_date_edit.setDateTime(QDateTime(2025, 8, 7, 0, 0))        self.start_date_edit.setDisplayFormat("yyyy-MM-dd")        basic_layout.addWidget(self.start_date_edit, 2, 1)        basic_layout.addWidget(QLabel("结束日期:"), 3, 0)        self.end_date_edit = QDateTimeEdit()        self.end_date_edit.setCalendarPopup(True)        self.end_date_edit.setDateTime(QDateTime(2025, 8, 14, 0, 0))        self.end_date_edit.setDisplayFormat("yyyy-MM-dd")        basic_layout.addWidget(self.end_date_edit, 3, 1)        # 输出文件        basic_layout.addWidget(QLabel("输出文件:"), 4, 0)        output_layout = QHBoxLayout()        self.output_file_edit = QLineEdit("公众号文章列表.xlsx")        output_layout.addWidget(self.output_file_edit)        browse_btn = QPushButton("浏览...")        browse_btn.setMaximumWidth(80)        browse_btn.clicked.connect(self.browse_output_file)        browse_btn.setStyleSheet("""            QPushButton {                background-color: #6c757d;                padding: 5px 10px;            }            QPushButton:hover {                background-color: #5a6268;            }        """)        output_layout.addWidget(browse_btn)        basic_layout.addLayout(output_layout, 4, 1)        layout.addWidget(basic_group)        # 进度组        progress_group = QGroupBox("进度")        progress_layout = QVBoxLayout(progress_group)        self.progress_bar = QProgressBar()        self.progress_bar.setValue(0)        progress_layout.addWidget(self.progress_bar)        self.status_label = QLabel("就绪")        self.status_label.setStyleSheet("color: #28a745; font-weight: bold;")        progress_layout.addWidget(self.status_label)        layout.addWidget(progress_group)        return widget    def create_log_widget(self):        """创建日志区域"""        widget = QWidget()        layout = QVBoxLayout(widget)        # 标签页        tab_widget = QTabWidget()        # 运行日志标签页        log_tab = QWidget()        log_layout = QVBoxLayout(log_tab)        self.log_text = LogTextEdit()        log_layout.addWidget(self.log_text)        tab_widget.addTab(log_tab, "运行日志")        # 统计信息标签页        stats_tab = QWidget()        stats_layout = QVBoxLayout(stats_tab)        self.stats_table = QTableWidget()        self.stats_table.setColumnCount(2)        self.stats_table.setHorizontalHeaderLabels(["项目", "数值"])        self.stats_table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Stretch)        self.stats_table.verticalHeader().setVisible(False)        stats_layout.addWidget(self.stats_table)        tab_widget.addTab(stats_tab, "统计信息")        layout.addWidget(tab_widget)        return widget    def browse_output_file(self):        """浏览输出文件路径"""        file_path, _ = QFileDialog.getSaveFileName(            self,            "保存文件",            self.output_file_edit.text(),            "Excel文件 (*.xlsx)"        )        if file_path:            self.output_file_edit.setText(file_path)    def start_task(self):        """开始任务"""        # 获取配置        config = {            'target_wechat': self.wechat_name_edit.text(),            'proxy_host': self.proxy_host_edit.text(),            'proxy_port': int(self.proxy_port_edit.text()),            'start_date': self.start_date_edit.date().toString("yyyy-MM-dd"),            'end_date': self.end_date_edit.date().toString("yyyy-MM-dd"),            'output_file': self.output_file_edit.text()        }        # 验证配置        if not config['target_wechat']:            QMessageBox.warning(self, "警告", "请输入公众号名称")            return        # 禁用开始按钮,启用停止按钮        self.start_btn.setEnabled(False)        self.stop_btn.setEnabled(True)        self.progress_bar.setValue(0)        self.status_label.setText("运行中...")        self.status_label.setStyleSheet("color: #0078d4; font-weight: bold;")        self.log_text.clear()        # 创建并启动工作线程        self.work_thread = WorkThread(config)        self.work_thread.log_signal.connect(self.log_text.append_log)        self.work_thread.progress_signal.connect(self.progress_bar.setValue)        self.work_thread.finished_signal.connect(self.on_task_finished)        self.work_thread.result_signal.connect(self.on_task_result)        self.work_thread.start()    def stop_task(self):        """停止任务"""        if self.work_thread and self.work_thread.isRunning():            self.work_thread.terminate()            self.work_thread.wait()            self.log_text.append_log("[警告] 用户手动停止任务")            self.on_task_finished(False, "任务已停止")    def on_task_finished(self, success, message):        """任务完成回调"""        self.start_btn.setEnabled(True)        self.stop_btn.setEnabled(False)        self.progress_bar.setValue(100 if success else 0)        if success:            self.status_label.setText("完成")            self.status_label.setStyleSheet("color: #28a745; font-weight: bold;")            QMessageBox.information(self, "完成", message)        else:            self.status_label.setText("失败")            self.status_label.setStyleSheet("color: #dc3545; font-weight: bold;")            QMessageBox.critical(self, "错误", message)    def on_task_result(self, result):        """任务结果回调"""        # 更新统计信息表格        self.stats_table.setRowCount(3)        self.stats_table.setItem(0, 0, QTableWidgetItem("文章总数"))        self.stats_table.setItem(0, 1, QTableWidgetItem(str(result.get('total', 0))))        self.stats_table.setItem(1, 0, QTableWidgetItem("成功捕获"))        self.stats_table.setItem(1, 1, QTableWidgetItem(str(result.get('captured', 0))))        self.stats_table.setItem(2, 0, QTableWidgetItem("输出文件"))        self.stats_table.setItem(2, 1, QTableWidgetItem(result.get('output_file', '')))        # 设置表格样式        for i in range(3):            for j in range(2):                item = self.stats_table.item(i, j)                if item:                    item.setTextAlignment(Qt.AlignmentFlag.AlignCenter)def main():    """主函数"""    app = QApplication(sys.argv)    app.setStyle('Fusion')    window = MainWindow()    window.show()    sys.exit(app.exec())if __name__ == "__main__":    main()

      最终将指定的微信公众号所有文章按照'公众号', '用户名', '文章标题', '作者', '发布时间', '原创', '封面图片', '摘要', '文章短链接', '文章长链接', '阅读数', '在看或推荐数', '转发数', '点赞数', '评论数', '收藏数'等字段进行统计记录并保存为excel表,实现了之前既定的需求....

      通过上面Python自动化脚本,仅用几分钟的时间就完成原需手动操作数小时甚至数天的工作任务。从最初准备手动人工机械操作的麻木到用python实现高效自动化的畅快,工作效率获得指数级提升,终于实现了不加班熬夜的自由!

      大佬们也可以举一反三,参照上面的代码思路根据自己工作中的实际情况来具体问题具体分析,实现自己定制化的需求。

      结语

      当Python遇见办公,牛马打工人终于笑出了猪叫声

      【职场人必看】每天早上一睁眼,想到又要面对:

      1.📊 堆积如山的Excel表格

      2.📑 机械重复的复制粘贴

      3.✍️ 永远改不完的各类文档

      4.诸如此类的更多........

      是不是连Ctrl+Alt+Delete的心都有了?

      别慌!别急,摸鱼这位“职场外挂”已经带着Python代码来拯救你了!

      友情提示:考虑到没有python环境的朋友需要打包好的成品exe,摸鱼早已贴心打包好,本篇文章代码打包的exe截图如下:

      另外,《码海听潮》公众号所有文章码和exe程序已打包好上传绿联nas私有云,有需要的大佬扫一扫上面博主的个人微信二维码,需要的大佬需支付9.9元永久拥有公众号资源(写原创干货费时费力,属实不易),邀请您进入社区群获取下载链接!!,群内提供python办公自动化交流问题,解决问题,且码海听潮微信公众号文章发布会第一时间会更新到群里,非诚勿扰哈!

      码海听潮官方社区群如下:

      赶紧微信扫一扫下方二维码添加摸鱼君微信

      最新文章

      随机文章