confluence_table数据爬取

news2024/11/25 22:47:19

需求场景:

  获取指定confluence文档中的表格数据,同时将页面中的附件下载在指定的文件夹中。
在这里插入图片描述

实现步骤:

  1. 开启confluence的远程api端口
    在这里插入图片描述

  2. 选择使用的接口。 可以参考 官方接口文档 。

  3. 当前示例用到的接口为:

    Get content /rest/api/content/{content_id}

    Content - attachments /rest/api/content/{content_id}/child/attachment

  4. 调用接口,查看接口返回的数据是否满足要求。

    • 首先获取文档内容:/rest/api/content/{content_id}
      在这里插入图片描述

      没有需要的表格内容。

      先来看一下如果使用接口创建一个content需要传递什么参数,参考 官方文档 , 示例参数中有一个body结构体,而获取文档接口返回值中没有该内容。

      在这里插入图片描述

      在获取文档内容结构中添加参数 ?expand=body.storage , 即获取body结构体中的storage对象。再次查看接口返回值:

         注意:
                 
         接口返回的表格数据和我们在页面看到的表格相比,缺失了部分内容。比如含有json、zip文件的列。
         
         接口返回的表格数据不会包含其他页面的引入数据。可以点击编辑查看本页面的数据。
      

      在这里插入图片描述
      在这里插入图片描述

         接口返回值中,多的内容像是html的表格内容。我们可以`pandas.read_html()`直接读取这个表数据。
      
    • 查看文档附件接口的内容: /rest/api/content/{content_id}/child/attachment

      在这里插入图片描述

  5. 编码实现功能:

    
    import os
    import re
    from datetime import datetime
    
    import pandas as pd
    import requests
    from clint.textui import progress
    from sqlalchemy import create_engine
    
    
    def confirm_path_exists(path):
        if not os.path.exists(path):
            os.makedirs(path)
    
    
    def is_url(url):
        pattern = re.compile("^([hH][tT]{2}[pP]://|[hH][tT]{2}[pP][sS]://)(([A-Za-z0-9-~]+).)+([A-Za-z0-9-~\\/])+$")
        match_obj = pattern.match(url)
    
        if match_obj != None:
            return True
        else:
            return False
    
    
    def get_df_from_html(html, table_index=0):
        """
            获取html中的表格
        :param html: html数据
        :param table_index: 表格的编号,标定数据表格一般是第一个,drsu数据表格一般为最后一个
        :return: 表格数据
        """
        df = pd.read_html(html)
        # 表数据处理
        # 获取table数据
        if len(df) == 0:
            print('页面没有table结构')
            return False, '页面没有table结构'
        df_with_zip = df[table_index]
    
        return df_with_zip
    
    
    confluence_host = 'http://172.18.3.2:8090'
    mmp_host = 'http://127.0.0.1:5000'
    
    
    def get_content(session, content_id=7209464):
        """
            获取指定页面的内容
        :param session: 
        :param content_id: 
        :return: 
        """
        url = confluence_host + f'/rest/api/content/{content_id}?expand=body.storage'
        res = session.get(url)
    
        return res
    
    
    def get_attachments(session, content_id=7209464):
        """
            获取页面的附件
        :param session: 会话
        :param content_id: 页面id
        :return: 附件列表
        """
        url = confluence_host + f'/rest/api/content/{content_id}/child/attachment'
        res = session.get(url)
    
        content_attachments = []
        if res.status_code == 200:
            res_data = res.json()
            content_attachments.extend(res_data['results'])
            while res_data['size'] >= res_data['limit']:
                if 'next' in res_data['_links']:
                    next_url = confluence_host + res_data['_links']['next']
                else:
                    print(f'缺少翻页的链接: {res_data["_links"]}')
                    break
    
                res = session.get(next_url)
                if res.status_code == 200:
                    res_data = res.json()
                    content_attachments.extend(res_data['results'])
    
        else:
            print(f'获取附件出错:{res.text}')
    
        return content_attachments
    
    
    def get_zip_file_list(attachments_list):
        """
            筛选出zip类型的附件信息
        :param attachments_list: 附件列表
        :return:
        """
        zip_file_list = []
        for attachment in attachments_list:
            # 判断是否是zip文件
            if attachment['extensions']['mediaType'] == 'application/zip':
                # 将节点中的信息格式化处理
                down_host = attachment['_links']['self'].split('/rest')[0]
                zip_file_list.append({
                    'file_name': attachment['title'],
                    'file_href': down_host + attachment['_links']['download'],
                })
        print(zip_file_list)
        return zip_file_list
    
    
    def write_db(df, table_name, engine):
        # 写入数据库
        df.to_sql(table_name, con=engine, if_exists='append', index=False)
    
    
    
    def download_file(session, url, save_dir='./', file_name=None):
        """
            根据url将文件下载至指定位置
        :param save_dir: 
        :param url: 下载地址
        :param save_path: 保存路径
        :return:
        """
        # 确认路径是否存在
        confirm_path_exists(save_dir)
    
        # url合法性校验
        if not is_url(url):
            return False, 'url 不合法'
    
        if file_name is None:
            if '?' in url:
                url = url.split('?')[0]
            file_name = url.split('/')[-1]
        save_path = os.path.join(save_dir, file_name)
    
        # 文件下载
        res = session.get(url)
        if res.status_code != 200:
            print(res.text)
            return False, res.text
    
        try:
            with open(save_path, 'wb') as f:
                # 添加进度条
                total_length = int(res.headers.get('content-length'))
                for chunk in progress.bar(res.iter_content(chunk_size=2391975), expected_size=(total_length / 1024) + 1):
                    if chunk:
                        f.write(chunk)
                        f.flush()
            if not os.path.isfile(save_path):
                return False, '文件下载失败。'
        except Exception as e:
            print(f'错误信息: {str(e)}')
            return False, str(e)
    
        return True, '成功'
    
    
    def inset_table(session, html_id=7209464, table_name='version_upgrade',
                        engine=create_engine(f'sqlite:///cal.db', encoding='utf8')):
        res = get_content(session, html_id)
    
        if res.status_code == 200:
            # 标定文件表数据
            html_view = res.json()['body']['storage']['value']
            df = get_df_from_html(html_view)
    
            write_db(df, table_name, engine)
    
    
    def download_cal_and_update_table(session, html_id, save_dir):
        # 标定附件
        attachments = get_attachments(session, html_id)
        # 标定文件下载信息
        file_info = get_zip_file_list(cal_attachments)
        for zip_file in file_info:
            url = zip_file['file_href']
            file_name = zip_file['file_name']
            download_status, msg = download_file(session, url, save_dir)
    
    
    def main():
        # 登录cookies,因为confluence设置了登录验证码,所以这里直接使用cookie跳过登录操作
        header = {
            'Cookie': 'JSESSIONID=404FEBB859A8D689A590BCE4BE574F'
        }
    
        # 导入的表名
        table_name = 'cal_version_upgrade'
        # 导入的数据库
        db_path = r'D:\work\drsu_mmp\drsu_mmp_backend\config\drsu.db'
        engine = create_engine(f'sqlite:///{db_path}', encoding='utf8')
    
        # 下载标定文件保存位置
        save_dir = r'D:\home\drsu_mmp\upgrade\calibration\'
    
        # confluence标定文档id
        html_id = 7209464
    
        session = requests.session()
        session.headers = header
    
        # 将标定文档中的数据插入表数据
        inset_cal_table(session, html_id=html_id, table_name=table_name, engine=engine)
        # 根据标定文档和drsu文档信息更新标定版本记录表数据
        download_zip_and_update_table(session, cal_html_id, proj_id, save_dir)
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/722745.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

现在开始学linux驱动内核好吗?

一开始是觉得,内核诶,高大上。然后看了几个月驱动后,是认认真真的钻了几个月源码,写了很多学习笔记的那种。 先说好处吧,对基础能力的提升很明显。比如内核数据结构,指针,以及如何用c需要去完成…

Windows系统上安装Node.js图文步骤流程

Windows系统上安装Node.js图文步骤流程,本文以安装Node.js v4.4.3 LTS(长期支持版本)版本为例: 目录 Node.js下载 Windows 上安装 Node.js 1、Windows 安装包(.msi) 2、Windows 二进制文件 (.exe)安装 版本测试 Node.js下载 Node.js 安装包及源码…

Linux扩容和删除运行内存(swapfile 交换文件)

1 新增swapfile 交换文件 Linux中Swap(即:交换分区),类似于Windows的虚拟内存,就是当内存不足的时候,把一部分硬盘空间虚拟成内存使用,从而解决内存容量不足的情况。Android是基于Linux的操作系统&#xf…

Cyclo(L-Pro-L-Trp-),38136-70-8,L型氨基酸环二肽,及其参数说明

(文章资料汇总来源于:陕西新研博美生物科技有限公司小编MISSwu) 为大家介绍(CAS:38136-70-8),试剂仅用于科学研究,不可用于人类,非药用,非食用。 分子式:C16…

vscode的代码工作区实现机制

工作区是编辑器的重要部分,它承载着编辑器和本地文件的连接,对文件增、删、改、查。下面我会介绍vscode工作区的创建。同样我们知道vscode软件打开的时候没有默认工作区,这里我对它进行了改造,软件启动时指向默认工作区。 工作区目…

使用PLSQL导入excel数据

1、写查询语句,查询需要修改的表,并在语句后加for update。 select * from bn_inf_apply for update 2、打开excel,整理需要导入的数据,需要注意两点: 1、将标题行删除。 2、在首列左侧增加一个空白行 3、 选中exce…

React02-JSX 语法

一、React 基础知识 1. React.createElement React.createElement 是 jsx 语法的编译结果,这个函数用来创建一个 React 元素,它的返回值是一个 Virtual DOM(虚拟DOM)。 React.createElement(type, props, ...children) 第一个…

数据库之MySQL仓库安装

目录 数据库之MySQL仓库安装 在官方文档获得安装地址 点击链接进入后,选择 MySQL Yum Repository 进入网页后,选择自己Linux所对应的版本(我的是Linux8) 选择No thanks,juststart my download 选择复制链接地址 …

12.1 计算机硬件基础

目录 底层课程导学 课程回顾 1.编程基础 2.应用开发(使用操作系统提供的函数开发应用程序) 3.底层开发(开发操作系统本身,向下管理硬件、向上提供接口(API)) 嵌入式系统分层 应用开发 底…

PLC技能引领自动化控制系统的设计与开发

学习了PLC后,您可以从事各种与自动化控制系统相关的工作。以下是一些可能的职业方向: 自动化工程师:作为自动化工程师,您将负责设计、开发和维护自动化控制系统,其中包括PLC编程、传感器和执行器的集成以及系统调试和…

CAD怎么转JPG图片?三种方法教你快速转换

CAD文件只能在安装了CAD软件的电脑上打开,而JPG图片可以在几乎所有设备上打开,包括电脑、手机和平板电脑等,这样可以更方便地分享和传递设计文件。无需考虑对方是否有安装CAD软件。那么我们怎么把CAD文件转换成JPG图片呢?教大家三…

管理类联考——英语——趣味篇——不择手段——c开头单词

🏠个人主页:fo安方的博客✨ 💂个人简历:大家好,我是fo安方,考取过HCIE Cloud Computing、CCIE Security、CISP、RHCE、CCNP RS、PEST 3等证书。🐳 💕兴趣爱好:b站天天刷&…

CMIS_GOV_STD

自然资源“一张图”综合管理系统【标准版】

shell脚本-cp命令复制目录报错cp: omitting directory

cp 复制目录报错,如下: 【报错原因】: cp命令默认是不能复制目录的,需要加参数 【解决办法】: 使用cp -r命令进行复制,递归处理,将指定目录下的所有文件与子目录一并处理。 【拓展】cp语法 cp…

数据标注:数字病理学中的人工智能

在数字病理学中,组织样本的显微图像被传输到计算机,并使用先进的图像处理技术和计算机视觉对其进行分析。 医学图像和诊断的数字化为病理学中的人工智能开辟了途径。病理学家可以使用机器学习模型来进行增强分析并提高结果准确性。此外,病理学…

socat: 网络链接和一些简易的RPC

除了这些功能之外,端口转发,也是相当的方便实用, 小型产品的RPC 都可以通过,指定程序去执行

华为OD机试真题B卷 Python 实现【整理扑克牌】,附详细解题思路

目录 一、题目描述步骤1步骤2步骤3 二、输入描述三、输出描述四、解题思路五、Python算法源码六、效果展示1、输入2、输出3、说明 一、题目描述 给定一组数字,表示扑克牌的牌面数字,忽略扑克牌的花色,请按如下规则对这一组扑克牌进行整理&am…

使用kubeshpere创建k8s容器日志系统grafana-loki

k8s日志聚合平台grafana-loki,可以统一查看所有容器的日志运行。 效果: 使用kubeshpere创建loki应用十分的方便,减少了很多操作,易用的同时也实用,k8s不再是精通人员才能使用的编排系统。 1、在企业空间中&#xff0…

100种思维模型之能力圈思维模型-91

芒格说: “ 一个人在一生中可以真正得到的真见卓识仍然非常有限,所以正确的决策必须局限在自己的 ‘ 能力圈’ 以内。 ” 巴菲特说: “对你的 能力圈 来说,最重要的不是能力圈的范围大小,而是你如何能够 确定能…

虹科教程 | Linux网络命名空间与虹科PROFINET协议栈的GOAL中间件结合使用

前言 PROFINET是由PI推出的开放式工业以太网标准,它使用TCP/IP等IT标准,并由IEC 61158和IEC 61784 标准化,具有实时功能,并能够无缝集成到现场总线系统中。凭借其技术的开放性、灵活性和性能优势,PROFINET可应用于过程…