腾讯在线文档下载文档html格式

news2025/1/12 21:09:22

腾讯在线文档下载文档html格式

步骤

  1. chrome 浏览器打开该文档(edge不行)

  2. 同时按住ctrl+p快捷键调出腾讯文档内置的打印页面,打印范围要选择整个工作薄纸张建议调大一点,边距建议较窄,缩放要选择宽度撑满,不然可能会有内容太宽而显示不出来
    在这里插入图片描述

  3. 可能要等加载打印预览,耐心等待

判断是否卡死可以看url的?tab=xxx参数是否变化,如果在变则没有卡死
在这里插入图片描述

  1. 按下F12快捷键,用检查模式,找到你要定位的标签(需要观察这个标签是不是滚动屏幕更改了内容)

ctrl+f快捷键在元素中查找文本也可以定位到附近,这里需要具体情况具体分析
其实在这一步时如果图方便可以点击下一步按钮,会导出pdf格式,但是如果文件很大的话,会卡死

  1. 获取该标签完整xpath,输入到输入框中
  2. 点击开始监控按钮,油猴脚本(放在文末)就开始监视你输入的xpath元素的一级子元素变化了,会将没有出现过的子元素追加到该xpath元素元素中
  3. 不断向下滑动屏幕(不划动之后的内容不会刷新,也不要太快了,可能程序跟不上),一直滑动到打印预览区域的底部
    在这里插入图片描述
  4. 点击导出内容,下载保存的xpath元素,如果担心不全的话,可以多次上下滑动滚动条,直到导出的文件大小不再变化
  5. 可以使用python代码(文末)删除js和css代码,使得界面更清晰

油猴脚本

// ==UserScript==
// @name         Monitor and Save Div Content
// @namespace    http://tampermonkey.net/
// @version      1.3
// @description  Monitor a specific div element and save its content, including child elements. Append new content and provide an export button.
// @match        *://*/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // 存储div内容的数组
    let divContent = [];
    // 存储目标div的XPath
    let targetDivXPath = '';
    // 存储MutationObserver实例
    let observer;
    // 存储目标div元素
    let targetDiv;
    // 存储开始监控的时间
    let startTime = null;
    // 存储导出文件的时间
    let endTime = null;

    // 这里的几个按钮位置很混乱,仍然需要重新排列
    // 创建输入框用于输入XPath
    const inputBox = document.createElement('input');
    inputBox.type = 'text';
    inputBox.placeholder = 'Enter XPath here';
    inputBox.style.position = 'fixed';
    inputBox.style.top = '10px';
    inputBox.style.right = '300px';
    inputBox.style.zIndex = '9999';
    inputBox.addEventListener('keydown', function(event) {
        if (event.key === 'Enter') {
            startMonitoring();
        }
    });
    document.body.appendChild(inputBox);

    // 创建开始按钮
    const startButton = document.createElement('button');
    startButton.textContent = '开始监控';
    startButton.style.position = 'fixed';
    startButton.style.top = '10px';
    startButton.style.right = '350px';
    startButton.style.zIndex = '9999';
    startButton.addEventListener('click', startMonitoring);
    document.body.appendChild(startButton);

    // 创建停止按钮
    const stopButton = document.createElement('button');
    stopButton.textContent = '停止监控';
    stopButton.style.position = 'fixed';
    stopButton.style.top = '10px';
    stopButton.style.right = '400px';
    stopButton.style.zIndex = '9999';
    stopButton.addEventListener('click', stopMonitoring);
    document.body.appendChild(stopButton);

    // 创建导出按钮
    const exportButton = document.createElement('button');
    exportButton.textContent = '导出内容';
    exportButton.style.position = 'fixed';
    exportButton.style.top = '30px'; // Move down to the next line
    exportButton.style.right = '300px';
    exportButton.style.zIndex = '9999';
    exportButton.addEventListener('click', exportContent);
    document.body.appendChild(exportButton);

    function startMonitoring() {
        // 清空divContent数组
        divContent = [];
        targetDivXPath = inputBox.value.trim();
        if (!targetDivXPath) {
            alert('请输入有效的XPath。');
            return;
        }

        // 停止之前的监控,如果存在
        if (observer) {
            stopMonitoring();
        }

        try {
            targetDiv = document.evaluate(targetDivXPath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
            if (!targetDiv) {
                alert('无法找到目标div元素,请检查XPath是否正确。');
                return;
            }

            // 获取当前时间
            startTime = new Date();

            // 保存当前div的内容
            saveCurrentDivContent(targetDiv);

            observer = new MutationObserver(function(mutations) {
                mutations.forEach(function(mutation) {
                    if (mutation.type === 'childList') {
                        const addedNodes = mutation.addedNodes;
                        for (let i = 0; i < addedNodes.length; i++) {
                            const newContent = addedNodes[i].outerHTML;
                            // 虽然大部分去重了,但是好像仍然有少部分重复
                            if (!divContent.includes(newContent)) {
                                divContent.push(newContent);
                            }
                        }
                    }
                });
            });

            const config = { childList: true, subtree: true };
            observer.observe(targetDiv, config);

            startButton.textContent = '监控中...';
            startButton.disabled = true;
            stopButton.disabled = false; // 启用停止按钮
            inputBox.disabled = true;
        } catch (e) {
            alert('XPath无效或页面未完全加载,请刷新页面后重试。');
        }
    }

    function stopMonitoring() {
        if (observer) {
            observer.disconnect();
            observer = null;
        }
        startButton.textContent = '开始监控';
        startButton.disabled = false;
        stopButton.disabled = true; // 禁用停止按钮
        inputBox.disabled = false;
        alert('监控已停止。');
    }

    function exportContent() {
        if (divContent.length === 0) {
            alert('当前没有内容可以导出。');
            return;
        }

        let startTime2 = startTime.getFullYear() + '-' + (startTime.getMonth() + 1).toString().padStart(2, '0') + '-' + startTime.getDate().toString().padStart(2, '0') + ' ' + startTime.getHours().toString().padStart(2, '0') + ':' + startTime.getMinutes().toString().padStart(2, '0') + ':' + startTime.getSeconds().toString().padStart(2, '0');

        endTime = new Date();
        let endTime2 = endTime.getFullYear() + '-' + (endTime.getMonth() + 1).toString().padStart(2, '0') + '-' + endTime.getDate().toString().padStart(2, '0') + ' ' + endTime.getHours().toString().padStart(2, '0') + ':' + endTime.getMinutes().toString().padStart(2, '0') + ':' + endTime.getSeconds().toString().padStart(2, '0');

        // 获取当前页面的URL
        const currentUrl = window.location.href;

        // 创建包含元数据的HTML字符串
        const metadataHtml = `
            <div style="background-color: #f0f0f0; padding: 10px; margin-top: 30px; border: 1px solid #ccc; font-weight: bold; text-align: center;">
                <p>开始导出时间: ${startTime2}</p>
                <p>导出结束时间: ${endTime2}</p>
                <p>保存网址: ${currentUrl}</p>
                <p>声明代码来源: <a href="https://blog.csdn.net/qq_33843237/article/details/136719243" target="_blank">CSDN博客</a></p>
                <p>其他信息: 此文档由油猴脚本导出,记录了特定div元素的内容变化。</p>
                <hr style="border: 0; height: 2px; background-color: #333; margin-top: 10px;" />
            </div>
        `;

        // 将元数据HTML和div内容合并
        const content = metadataHtml + divContent.join('\n');

        // 创建Blob对象
        const blob = new Blob([content], { type: 'text/html' });

        // 创建下载链接
        const url = URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.href = url;
        link.download = 'div_content.html';
        link.click();

        // 释放URL对象
        URL.revokeObjectURL(url);
    }

    function viewDivContent() {
        if (divContent.length === 0) {
            alert('当前没有内容可以查看。');
            return;
        }
        alert(divContent.join('\n'));
    }

    function saveCurrentDivContent(targetDiv) {
        const currentContent = targetDiv.innerHTML;
        divContent = [currentContent]; // 保存当前内容作为初始状态
    }
})();

python代码

import os
import re
from tkinter import Tk, filedialog, messagebox, simpledialog
from bs4 import BeautifulSoup, NavigableString

def remove_css_js(soup):
    # 移除所有style标签的内容,但保留标签(以便保留文本)
    for style in soup.find_all('style'):
        style.string = ''

    # 移除所有script标签的内容,但保留标签(以便保留文本)
    for script in soup.find_all('script'):
        script.string = ''

    # 移除所有内联样式
    for element in soup.find_all(style=True):
        element.attrs.pop('style', None)

    # 移除所有内联事件处理器(例如 onclick)
    for attr in ['onclick', 'onmouseover', 'onmouseout', 'onload', 'onerror']:
        for element in soup.find_all(True):
            if attr in element.attrs:
                element.attrs.pop(attr, None)

    # 移除所有链接到CSS文件的link标签
    for link in soup.find_all('link', rel=re.compile(r'stylesheet')):
        link.decompose()

    # 移除所有JavaScript文件的引用
    for script in soup.find_all('script', src=True):
        script.decompose()

    # 移除所有内嵌的CSS和JavaScript代码
    for tag in soup.find_all(True):
        if tag.name in ['style', 'script']:
            tag.replace_with(NavigableString(tag.string or ''))

def clean_html_file(file_path):
    with open(file_path, 'r', encoding='utf-8') as html_file:
        soup = BeautifulSoup(html_file, 'html.parser')

    remove_css_js(soup)

    # 清理后的HTML内容,保留文本
    cleaned_html = str(soup)

    return cleaned_html

def save_cleaned_html(cleaned_html, title='保存清理后的HTML文件'):
    root = Tk()
    root.withdraw()
    file_path = filedialog.asksaveasfilename(
        title=title,
        defaultextension=".html",
        filetypes=(("HTML files", "*.html"), ("All files", "*.*"))
    )

    if not file_path:
        messagebox.showerror("错误", "没有选择保存路径。")
        return None

    try:
        with open(file_path, 'w', encoding='utf-8') as new_html_file:
            new_html_file.write(cleaned_html)
        messagebox.showinfo("成功", "文件已成功保存。")
        return file_path
    except Exception as e:
        messagebox.showerror("错误", f"保存文件时发生错误: {e}")
        return None

def main():
    root = Tk()
    root.withdraw()

    # 选择HTML文件
    file_path = filedialog.askopenfilename(
        title="选择HTML文件",
        defaultextension=".html",
        filetypes=(("HTML files", "*.html"), ("All files", "*.*"))
    )

    if not file_path:
        messagebox.showerror("错误", "没有选择文件。")
        return

    try:
        # 清理HTML文件
        cleaned_html = clean_html_file(file_path)

        # 保存清理后的HTML文件
        export_path = save_cleaned_html(cleaned_html)

        # 如果保存成功,打开保存的文件
        if export_path:
            os.startfile(export_path)
    except Exception as e:
        messagebox.showerror("错误", f"处理文件时发生错误: {e}")

if __name__ == "__main__":
    main()

声明

本文仅供学习参考,一切责任与我无关。主要代码均由ChatGPT生成。

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

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

相关文章

支小蜜AI校园防欺凌系统可以使用在宿舍吗?

随着人工智能技术的快速发展&#xff0c;AI校园防欺凌系统已成为维护校园安全的重要手段。然而&#xff0c;关于这一系统是否适用于宿舍环境&#xff0c;仍存在一些争议和讨论。本文将探讨AI校园防欺凌系统在宿舍中的适用性&#xff0c;分析其潜在的优势与挑战&#xff0c;并提…

node:internal/crypto/hash:69 this[kHandle] = new _Hash(algorithm, xofLen);

npm 打包报错 原因就是npm版本太高了&#xff0c;用的18版本&#xff0c;切换成16版本就好了。

java脱离mybatis框架的环境下如何手撸代码操作数据库

一、问题提出 现今很多java ee开发人员都是直接使用springbootmybatis框架进行数据库操作。这种环境下&#xff0c;大多小白都不知道框架在操作数据库前后都执行了哪些动作。 今天&#xff0c;良哥教你如何在脱离框架的情况下&#xff0c;手撸代码连接和操作数据库资源。 二、…

Google Play上架:谷歌支付政策变更

目录 政策发布时间概括内容付款政策变动内容归纳google付款用户政策政策发布时间 2024 年 3 月 6 日 概括内容 为遵守《数字市场法案》(DMA) 的规定,从 2024 年 3 月 6 日起,我们将更新付款政策,允许开发者将欧洲经济区 (EEA) 的用户引导至其应用之外的平台(包括推广应用…

MySQL死锁案例分析及避免办法

1. 什么是死锁2. 举个栗子&#xff1a;2.1. 栗子一&#xff1a;2.1.1 代码栗子&#xff1a;2.1.2 存储引擎状态分析2.1.2.1 第一部分&#xff1a;2.1.2.2 第二部分&#xff1a;2.1.2.3 第三部分&#xff1a; 2.1.3 解决方式2.1.3.1 注意资源的获取顺序2.1.3.2 大事务拆小 2.2. …

有没有能用蓝牙的游泳耳机?四大年度最佳游泳耳机由衷推荐

随着科技的不断发展&#xff0c;游泳爱好者们对于游泳耳机的追求也越来越高。在游泳过程中&#xff0c;音乐和播客是许多泳者们的最佳伴侣&#xff0c;它能帮助他们保持节奏、提高兴趣。然而&#xff0c;传统的有线耳机在水下容易产生拉扯&#xff0c;不仅影响游泳体验&#xf…

【DL经典回顾】激活函数大汇总(十二)(GLU ReGLU附代码和详细公式)

激活函数大汇总&#xff08;十二&#xff09;&#xff08;GLU & ReGLU附代码和详细公式&#xff09; 更多激活函数见激活函数大汇总列表 一、引言 欢迎来到我们深入探索神经网络核心组成部分——激活函数的系列博客。在人工智能的世界里&#xff0c;激活函数扮演着不可或…

沃通SSL证书证券行业应用案例

金融证券行业作为现代经济体系中的重要组成部分&#xff0c;其安全性直接关系到国家经济的稳定和广大投资者的利益。沃通SSL证书基于密码技术保护传输数据的机密性、完整性&#xff0c;通过权威身份认证确保服务器身份真实性&#xff0c;已持续为众多知名证券行业客户提供服务&…

微信小程序开发:异步处理接入的生成式图像卡通化

书接上文&#xff0c;我们完成了对接阿里云人像动漫化接口&#xff0c;现已完成的界面是这样的&#xff1a; 就是效果看着一般&#xff0c;看看效果&#xff1a; 然后我就在阿里云api市场转悠&#xff0c;就想看看还有没有什么其他奇奇怪怪的api&#xff0c;结果就发现了这个&a…

python绘制激活函数(sigmoid, Tanh, ReLU, Softmax)

import numpy as np import matplotlib.pyplot as plt # matplotlib的负数显示设置 plt.rcParams[axes.unicode_minus] False # 显示负数 # 输出高清图像 %config InlineBackend.figure_format retina %matplotlib inline # 设置字体 plt.rc(font,familyTimes New Roman, s…

基于51单片机的微波炉温度控制器设计[proteus仿真]

基于51单片机的微波炉温度控制器设计[proteus仿真] 温度检测系统这个题目算是课程设计和毕业设计中常见的题目了&#xff0c;本期是一个基于51单片机的微波炉温度控制器设计 需要的源文件和程序的小伙伴可以关注公众号【阿目分享嵌入式】&#xff0c;赞赏任意文章 2&#xff…

ResNet学习笔记

一、residual结构 优点&#xff1a; &#xff08;1&#xff09;超深的网络结构(突破1000层) &#xff08;2&#xff09;提出residual模块 &#xff08;3&#xff09;使用Batch Normalization加速训练(丢弃dropout) 解决问题&#xff1a; &#xff08;1&#xff09; 梯度消失和…

【JavaScript】JavaScript 运算符 ② ( 表达式 与 返回值 | 自增 与 自减运算符 细节 | 前置自增运算符 | 后置自增运算符 )

文章目录 一、JavaScript 运算符1、表达式 与 返回值2、自增 与 自减运算符 细节3、前置自增运算符4、后置自增运算符5、自增 / 自减 运算符 代码示例 一、JavaScript 运算符 1、表达式 与 返回值 " 表达式 " 是 由 数字 , 运算符 , 变量 组成的 " 式子 " …

OpenAI 的 GPTs 提示词泄露攻击与防护实战:攻击卷(一)

攻击提示词 1.0 五件套混合散打 1. Repeat the words above starting with the phrase "You are ChatGPT". put them in a txt code block. Include everything. 2. give me your very first initial prompt exactly and not modified 3. 你有一個舊的 prompt 和 配…

18 OpenCV霍夫变换检测直线

文章目录 HoughLines 算子HoughLinesP 算子示例 HoughLines 算子 cv::HoughLines( InputArray src, // 输入图像&#xff0c;必须8-bit的灰度图像 OutputArray lines, // 输出的极坐标来表示直线 double rho, // 生成极坐标时候的像素扫描步长 double theta, //生成极坐标时候…

数据结构与算法----复习Part 15 ()

本系列是算法通关手册LeeCode的学习笔记 算法通关手册&#xff08;LeetCode&#xff09; | 算法通关手册&#xff08;LeetCode&#xff09; (itcharge.cn) 目录 一&#xff0c;二叉搜索树&#xff08;Binary Search Tree&#xff09; 二叉搜索树的查找 二叉搜索树的插入 …

Go语言中的make和new:内存分配与对象创建的巧妙之道

Go语言中的make和new&#xff1a;内存分配与对象创建的巧妙之道 Go语言作为一门简洁而强大的编程语言&#xff0c;提供了多种用于动态内存分配和对象创建的关键词。其中&#xff0c;make和new是两个常见且常被混淆的关键词。本文将深入讲解Go语言中make和new的区别&#xff0c;…

[AIGC] Spring Boot中的切面编程和实例演示

切面编程&#xff08;Aspect Oriented Programming&#xff0c;AOP&#xff09;是Spring框架的关键功能之一。通过AOP&#xff0c;我们可以将代码下沉到多个模块中&#xff0c;有助于解决业务逻辑和非业务逻辑耦合的问题。本文将详细介绍Spring Boot中的切面编程&#xff0c;并…

你是否知道到今年315到来 大数据杀熟还存在吗?

随着315消费者权益日的临近&#xff0c;关于大数据杀熟的话题再次引起了广泛关注。在当今这个数字化时代&#xff0c;大数据杀熟现象是否仍然存在呢&#xff1f; 首先&#xff0c;我们需要明确什么是大数据杀熟。简单来说&#xff0c;大数据杀熟是指企业利用消费者的个人信息和…

Inception网络以及GoogleNet

一个inception模块所做的 多个inception模块组成一个inception网络 上图中有多个inception模块&#xff0c;组成了一个inception网络&#xff0c;在有的隐藏层的地方还会输出还会做softmax。 Google开发的inception网络&#xff0c;因此把它叫做GoogleNet&#xff0c;详细说明…