confluence_table数据爬取

需求场景:

  获取指定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)
    
Python爬虫可以用于从Confluence(一种基于wiki的协作平台)抓取数据Confluence页面通常包含HTML结构,所以你可以使用Python的网络库如requests和BeautifulSoup、或者是更高级的第三方库如PyQuery或Selenium来完成爬取。 以下是基本步骤: 1. **安装所需库**:首先,你需要安装`requests`来发送HTTP请求,`beautifulsoup4`或`lxml`解析HTML内容。 ```bash pip install requests beautifulsoup4 ``` 2. **发送GET请求**:使用requests.get()函数获取Confluence页面的HTML源码。 ```python import requests url = "https://your-confluence-site.com/wiki/path-to-page" response = requests.get(url) html_content = response.text ``` 3. **解析HTML**:使用BeautifulSoup解析HTML,找到需要的数据元素。例如,如果你的目标是页面标题或特定类型的wiki页面链接,可以查找对应的HTML标签(如<h1>、<a>等)。 ```python from bs4 import BeautifulSoup soup = BeautifulSoup(html_content, 'html.parser') title = soup.find('h1').text # 获取页面标题 links = [a['href'] for a in soup.select('.link-type-you-care-about')] # 获取链接列表 ``` 4. **保存数据**:将抓取到的数据存储到文件或数据库中,根据你的需求进行处理。 注意: - Confluence可能有反爬虫策略,比如需要登录、设置User-Agent、节流请求频率等,你可能需要模拟浏览器行为或处理cookies。 - 遵循网站的robots.txt规则,尊重版权并避免对服务器造成过大压力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值