Ueditor富文本回显word文档(doc和docx格式都支持)进行二次编辑,springboot后端_ueditor编辑器 文档-程序员宅基地

技术标签: spring boot  

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

vue+ueditor+springboot, 实现word文档上传编辑

前言

`前端导入word文档(doc和docx格式都支持),Ueditor富文本回显进行二次编辑,目前ueditor项目archived了,实现两种格式的相关材料相对稀缺。

解决思路: 1.上传word文件 2.后台读取生成html文件 3.后台读取html文件内容返回给前端

赠人玫瑰,手留余香

一、目标

通过上传word文件,通过后台进行解析回显到前端。

在这里插入图片描述

二、代码步骤

后端代码结构:
在这里插入图片描述

1.maven依赖库

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.15</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.15</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>3.15</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>3.15</version>
        </dependency>

        <dependency>
            <groupId>fr.opensagres.xdocreport</groupId>
            <artifactId>org.apache.poi.xwpf.converter.xhtml</artifactId>
            <version>1.0.6</version>
        </dependency>

2.vue页面读取ueditor的配置

代码如下:

 /**
     *  获取UE文件上传配置
     * @param request
     * @param response
     * @throws IOException
     */
    @GetMapping(value = "/config")
    public void ueConfig(HttpServletRequest request, HttpServletResponse response) throws IOException {
    
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
        String urlPrefix = ueProperties.getSavepath();
        log.info("urlPrefix = "+urlPrefix);
        String exec = "{\n" +
                "    /* 上传图片配置项 */\n" +
                "    \"imageActionName\": \"catcherImage\", /* 执行上传图片的action名称 */\n" +
                "    \"imageFieldName\": \"upfile\", /* 提交的图片表单名称 */\n" +
                "    \"imageMaxSize\": 2048, /* 上传大小限制,单位B */\n" +
                "    \"imageAllowFiles\": [\".png\", \".jpg\", \".jpeg\", \".gif\", \".bmp\"], /* 上传图片格式显示 */\n" +
                "    \"imageCompressEnable\": true, /* 是否压缩图片,默认是true */\n" +
                "    \"imageCompressBorder\": 800, /* 图片压缩最长边限制 */\n" +
                "    \"imageInsertAlign\": \"none\", /* 插入的图片浮动方式 */\n" +
                "    \"imageUrlPrefix\": \"" + urlPrefix + "\", /* 图片访问路径前缀 */\n" +
                "    \"imagePathFormat\": \"/ueditor/image/{yyyy}{mm}{dd}/\", /* 上传保存路径,可以自定义保存路径和文件名格式 */\n" +
                "                                /* {filename} 会替换成原文件名,配置这项需要注意中文乱码问题 */\n" +
                "                                /* {rand:6} 会替换成随机数,后面的数字是随机数的位数 */\n" +
                "                                /* {time} 会替换成时间戳 */\n" +
                "                                /* {yyyy} 会替换成四位年份 */\n" +
                "                                /* {yy} 会替换成两位年份 */\n" +
                "                                /* {mm} 会替换成两位月份 */\n" +
                "                                /* {dd} 会替换成两位日期 */\n" +
                "                                /* {hh} 会替换成两位小时 */\n" +
                "                                /* {ii} 会替换成两位分钟 */\n" +
                "                                /* {ss} 会替换成两位秒 */\n" +
                "                                /* 非法字符 \\ : * ? \" < > | */\n" +
                "                                /* 具请体看线上文档: fex.baidu.com/ueditor/#use-format_upload_filename */\n" +
                "\n" +
                "    /* 涂鸦图片上传配置项 */\n" +
                "    \"scrawlActionName\": \"uploadscrawl\", /* 执行上传涂鸦的action名称 */\n" +
                "    \"scrawlFieldName\": \"upfile\", /* 提交的图片表单名称 */\n" +
                "    \"scrawlPathFormat\": \"/ueditor/image/{yyyy}{mm}{dd}/\", /* 上传保存路径,可以自定义保存路径和文件名格式 */\n" +
                "    \"scrawlMaxSize\": 2048000, /* 上传大小限制,单位B */\n" +
                "    \"scrawlUrlPrefix\": \"\", /* 图片访问路径前缀 */\n" +
                "    \"scrawlInsertAlign\": \"none\",\n" +
                "\n" +
                "    /* 截图工具上传 */\n" +
                "    \"snapscreenActionName\": \"uploadimage\", /* 执行上传截图的action名称 */\n" +
                "    \"snapscreenPathFormat\": \"/ueditor/image/{yyyy}{mm}{dd}/\", /* 上传保存路径,可以自定义保存路径和文件名格式 */\n" +
                "    \"snapscreenUrlPrefix\": \"\", /* 图片访问路径前缀 */\n" +
                "    \"snapscreenInsertAlign\": \"none\", /* 插入的图片浮动方式 */\n" +
                "\n" +
                "    /* 抓取远程图片配置 */\n" +
                "    \"catcherLocalDomain\": [\"127.0.0.1\", \"localhost\", \"img.baidu.com\"],\n" +
                "    \"catcherActionName\": \"catchimage\", /* 执行抓取远程图片的action名称 */\n" +
                "    \"catcherFieldName\": \"source\", /* 提交的图片列表表单名称 */\n" +
                "    \"catcherPathFormat\": \"/ueditor/image/{yyyy}{mm}{dd}/\", /* 上传保存路径,可以自定义保存路径和文件名格式 */\n" +
                "    \"catcherUrlPrefix\": \"" + urlPrefix + "\", /* 图片访问路径前缀 */\n" +
                "    \"catcherMaxSize\": 2048000, /* 上传大小限制,单位B */\n" +
                "    \"catcherAllowFiles\": [\".png\", \".jpg\", \".jpeg\", \".gif\", \".bmp\"], /* 抓取图片格式显示 */\n" +
                "\n" +
                "    /* 上传视频配置 */\n" +
                "    \"videoActionName\": \"uploadvideo\", /* 执行上传视频的action名称 */\n" +
                "    \"videoFieldName\": \"upfile\", /* 提交的视频表单名称 */\n" +
                "    \"videoPathFormat\": \"/ueditor/video/{yyyy}{mm}{dd}/\", /* 上传保存路径,可以自定义保存路径和文件名格式 */\n" +
                "    \"videoUrlPrefix\": \"\", /* 视频访问路径前缀 */\n" +
                "    \"videoMaxSize\": 10240000, /* 上传大小限制,单位B,默认10MB */\n" +
                "    \"videoAllowFiles\": [\n" +
                "        \".flv\", \".swf\", \".mkv\", \".avi\", \".rm\", \".rmvb\", \".mpeg\", \".mpg\",\n" +
                "        \".ogg\", \".ogv\", \".mov\", \".wmv\", \".mp4\", \".webm\", \".mp3\", \".wav\", \".mid\"], /* 上传视频格式显示 */\n" +
                "    /* 上传文件配置 */\n" +
                "    \"fileActionName\": \"uploadfile\", /* controller里,执行上传视频的action名称 */\n" +
                "    \"fileFieldName\": \"upfile\", /* 提交的文件表单名称 */\n" +
                "    \"filePathFormat\": \"/ueditor/file/{yyyy}{mm}{dd}/\", /* 上传保存路径,可以自定义保存路径和文件名格式 */\n" +
                "    \"fileUrlPrefix\": \"\", /* 文件访问路径前缀 */\n" +
                "    \"fileMaxSize\": 10240000, /* 上传大小限制,单位B,默认10MB */\n" +
                "    \"fileAllowFiles\": [\n" +
                "        \".png\", \".jpg\", \".jpeg\", \".gif\", \".bmp\",\n" +
                "        \".flv\", \".swf\", \".mkv\", \".avi\", \".rm\", \".rmvb\", \".mpeg\", \".mpg\",\n" +
                "        \".ogg\", \".ogv\", \".mov\", \".wmv\", \".mp4\", \".webm\", \".mp3\", \".wav\", \".mid\",\n" +
                "        \".rar\", \".zip\", \".tar\", \".gz\", \".7z\", \".bz2\", \".cab\", \".iso\",\n" +
                "        \".doc\", \".docx\", \".xls\", \".xlsx\", \".ppt\", \".pptx\", \".pdf\", \".txt\", \".md\", \".xml\"\n" +
                "    ], /* 上传文件格式显示 */\n" +
                "    /* 列出指定目录下的图片 */\n" +
                "    \"imageManagerActionName\": \"listimage\", /* 执行图片管理的action名称 */\n" +
                "    \"imageManagerListPath\": \"/ueditor/image/{yyyy}{mm}{dd}/\", /* 指定要列出图片的目录 */\n" +
                "    \"imageManagerListSize\": 20, /* 每次列出文件数量 */\n" +
                "    \"imageManagerUrlPrefix\": \"" + urlPrefix + "\", /* 图片访问路径前缀 */\n" +
                "    \"imageManagerInsertAlign\": \"none\", /* 插入的图片浮动方式 */\n" +
                "    \"imageManagerAllowFiles\": [\".png\", \".jpg\", \".jpeg\", \".gif\", \".bmp\"], /* 列出的文件类型 */\n" +
                "    /* 列出指定目录下的文件 */\n" +
                "    \"fileManagerActionName\": \"listfile\", /* 执行文件管理的action名称 */\n" +
                "    \"fileManagerListPath\": \"/ueditor/file/{yyyy}{mm}{dd}/\", /* 指定要列出文件的目录 */\n" +
                "    \"fileManagerUrlPrefix\": \"\", /* 文件访问路径前缀 */\n" +
                "    \"fileManagerListSize\": 20, /* 每次列出文件数量 */\n" +
                "    \"fileManagerAllowFiles\": [\n" +
                "        \".png\", \".jpg\", \".jpeg\", \".gif\", \".bmp\",\n" +
                "        \".flv\", \".swf\", \".mkv\", \".avi\", \".rm\", \".rmvb\", \".mpeg\", \".mpg\",\n" +
                "        \".ogg\", \".ogv\", \".mov\", \".wmv\", \".mp4\", \".webm\", \".mp3\", \".wav\", \".mid\",\n" +
                "        \".rar\", \".zip\", \".tar\", \".gz\", \".7z\", \".bz2\", \".cab\", \".iso\",\n" +
                "        \".doc\", \".docx\", \".xls\", \".xlsx\", \".ppt\", \".pptx\", \".pdf\", \".txt\", \".md\", \".xml\"\n" +
                "    ] /* 列出的文件类型 */\n" +
                "}";
        PrintWriter writer = response.getWriter();
        writer.write(exec);
        writer.flush();
        writer.close();
    }

3.前端导入文件

代码如下:

 methods: {
    
        ready(editorInstance) {
    
          this.editorInstance=editorInstance
          async uploadWordFile(event) {
    
              const file = event.target.files[0];
              if (!file) return;
              // 将Word文件转换为HTML
              const htmlContent = await this.convertWordToHtml(file);
               const jsonData = JSON.parse(htmlContent)
               // 设置UEditor的内容
               console.log(jsonData)
               this.editorInstance.execCommand('inserthtml',jsonData.data)
          },
          async convertWordToHtml(wordFile) {
    
            // 这里应该是Word文件转HTML的后端接口调用代码
            // 假设有一个转换Word为HTML的后端API
            const formData = new FormData();
            formData.append('file', wordFile); 
            const response = await fetch('/api/ue/uploadFile',{
    
              method:'POST',
              body:formData
            })
            if (response.ok) {
    
              return await response.text();
            }
            throw new Error('转换失败');
          }
      },

4.后端读取文件生成html

代码如下:

/** word文档上传
     *
     * @param file
     * @return
     */
    @PostMapping("/uploadFile")
    public Object uploadFile(@RequestParam(name = "file") MultipartFile file){
    
        String filename = file.getOriginalFilename();
        JSONObject result = new JSONObject();
        String visitHtml = "";
        try {
    
            if (filename.endsWith(".docx")) {
    
                //TODO 处理docx格式的
                visitHtml = WordConverHtmlUtils.docxToHtmlText(file, ueProperties);
            } else if (filename.endsWith(".doc")) {
    
                //TODO 处理doc格式的
                visitHtml = WordConverHtmlUtils.docToHtmlText(file, ueProperties);
            } else {
    
                log.error("不支持的文件格式!");
            }
            result.put("state", "SUCCESS");
            result.put("data", visitHtml);
            log.info("result: {}", result.toString());
        } catch (Exception e) {
    
            log.error("文件找不到异常!");
            e.printStackTrace();
        }
        return result;
    }

5.WordConverHtmlUtils工具类

️️️️️
options.URIResolver(new BasicURIResolver(picUri));
这里需要设置为前端能过直接访问到的图片地址, 比如作者:http://localhost:8000/resource/ueditor/file/20240404/1712220732312.png,
️️️️️ 否则,ueditor编辑器无法显示word文档中的图片

代码如下:

package com.ue.demo.utils;

import cn.hutool.core.lang.UUID;
import com.ue.demo.config.UeProperties;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.converter.PicturesManager;
import org.apache.poi.hwpf.converter.WordToHtmlConverter;
import org.apache.poi.hwpf.usermodel.PictureType;
import org.apache.poi.xwpf.converter.core.BasicURIResolver;
import org.apache.poi.xwpf.converter.core.FileImageExtractor;
import org.apache.poi.xwpf.converter.xhtml.XHTMLConverter;
import org.apache.poi.xwpf.converter.xhtml.XHTMLOptions;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.web.multipart.MultipartFile;
import org.w3c.dom.Document;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * @author:Peanut
 * @create: 2024-04-05 10:22
 * @version: 1.0.0
 * @description:
 */
@Slf4j
public class WordConverHtmlUtils {
    
    private final static String FILE_URL_PRE = "/ueditor/file/";
    /**
     * 上传docx文档,返回解析后的Html
     */
    public static String docxToHtmlText(MultipartFile file, UeProperties ueProperties) throws Exception {
    
        try {
    
            String fileName = UUID.fastUUID().toString();
            //图片存放地址
            String imagePath = ueProperties.getSavepath().concat(FILE_URL_PRE).concat("/");
            String fileOutName = imagePath.concat(fileName).concat(".html");
            log.info("上传docx文档解析");
            log.info("上传docx文档,返回解析后的Html, imagePath:{}", imagePath);
            log.info("fileOutName:{}", fileOutName);
            //获取一个用操作Word的对象
            XWPFDocument document = new XWPFDocument(file.getInputStream());
            //导出为html时的一些基本设置类
            XHTMLOptions options = null;
            //判断word文件中是否有图片
            if(document.getAllPictures().size() > 0) {
    
                //获取默认的对象,设置缩进indent
                options = XHTMLOptions.getDefault().indent(4);
                // 如果包含图片的话,要设置图片的导出位置
                File imageFolder = new File(imagePath);
                //设置图片抽取器的目的地文件夹 用于存放图片文件
                options.setExtractor(new FileImageExtractor(imageFolder));
                // URI resolver  word的html中图片的目录路径
                //️️️️️️️️️️️️️️️️️
                //️️️️️ 这里需要设置为前端能过直接访问到的图片地址, 比如作者:http://localhost:8000/resource/ueditor/file/20240404/1712220732312.png,
                //️️️️️ 否则,ueditor编辑器无法显示word文档中的图片
                String picUri = ueProperties.getShowpath().concat(imagePath.substring(imagePath.indexOf("ueditor")));
                options.URIResolver(new BasicURIResolver(picUri));
            }

            //获取输出的html文件对象
            File outFile = new File(fileOutName);
            if(!outFile.getParentFile().exists()){
    
                outFile.getParentFile().mkdirs();
            }
            //创建所有的父路径,如果不存在父目录的话
            outFile.getParentFile().mkdirs();
            //创建一个输出流
            OutputStream out = new FileOutputStream(outFile);
            //html转换器
            XHTMLConverter.getInstance().convert(document, out, options);
            log.info("html转换器 success");
            //处理生成的html,字符串形式给前端
            return readHtmlStr(fileOutName);
        } catch (Exception e) {
    
            log.error("docxToHtmlText 解析异常", e);
        }
        return "";
    }

    /**
     * 上传doc格式Word文档,返回解析后的Html
     * @param file
     * @param ueProperties
     * @return
     * @throws Exception
     */
    public static String docToHtmlText(MultipartFile file, UeProperties ueProperties) throws Exception {
    
        //使用字符数组流获取解析的内容
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        OutputStream outStream = new BufferedOutputStream(baos);
        try {
    
            String fileName = UUID.fastUUID().toString();
            //将上传的文件传入Document转换
            //图片存放地址
            String docPath = ueProperties.getSavepath().concat(FILE_URL_PRE).concat("/");
            String imagePath = docPath.concat("image/");
            String fileOutName = docPath.concat(fileName).concat(".html");
            log.info("上传doc文档,返回解析 ");
            log.info("fileOutName:{}", fileOutName);
            //创建图片文件的存储目录
            new File(imagePath).mkdirs();
            //poi中doc文档对应的实体类
            HWPFDocument hwpfDocument = new HWPFDocument(file.getInputStream());
            //使用空的文档对象构建一个转换对象
            WordToHtmlConverter converter = new WordToHtmlConverter(DocumentBuilderFactory
                    .newInstance()
                    .newDocumentBuilder()
                    .newDocument());

            //设置存储图片的管理者--使用匿名内部类实现 该类实现了PicturesManager接口,实现了其中的savePicture方法
            converter.setPicturesManager(new PicturesManager() {
    
                FileOutputStream out = null;
                //在下面的processDocument方法内部会调用该方法 用于存储word中的图片文件
                @Override
                public String savePicture(byte[] bytes, PictureType pictureType, String name, float width, float height) {
    
                    try {
    
                        //单个照片的保存
                        out = new FileOutputStream(imagePath + name);
                        out.write(bytes);
                    } catch (IOException exception) {
    
                        exception.printStackTrace();
                    }finally {
    
                        if(out != null) {
    
                            try {
    
                                out.close();
                            } catch (IOException e) {
    
                                e.printStackTrace();
                            }
                        }
                    }
                    //这里要返回给操作者(HtmlDocumentFacade)一个存储的路径 用于生成Html时定位到图片资源
                    //️️️️️️️️️️️️️️️️️
                    //️️️️️ 这里需要设置为前端能过直接访问到的图片地址, 比如作者:http://localhost:8000/resource/ueditor/file/20240404/1712220732312.png,
                    //️️️️️ 否则,ueditor编辑器无法显示word文档中的图片
                    return ueProperties.getShowpath().concat(imagePath.substring(imagePath.indexOf("ueditor"))).concat(name);
                }
            });
            //使用外观模式,将hwpfDocument文档对象设置给HtmlDocumentFacade中的Document属性
            converter.processDocument(hwpfDocument);
            //获取转换器中的document文档
            Document htmlDocument = converter.getDocument();
            //充当文档对象模型 (DOM) 树形式的转换源树的持有者  -- 源树
            DOMSource domSource = new DOMSource(htmlDocument);

            //转换器 该对象用于将源树转换为结果树
            Transformer transformer = TransformerFactory.newInstance().newTransformer();
            //设置输出时的以什么方式输出,也可说是结果树的文件类型 可以是html/xml/text或者是一些扩展前三者的扩展类型
            transformer.setOutputProperty(OutputKeys.METHOD , "html");
            //设置一些必要的属性 设置输出时候的编码为utf-8
            transformer.setOutputProperty(OutputKeys.ENCODING , "utf-8");

            //转换 将输入的源树转换为结果树并且输出到streamResult中
            transformer.transform(domSource , new StreamResult(new File(fileOutName)));
            log.info("html转换器 success");
            //处理生成的html,字符串形式给前端
            return readHtmlStr(fileOutName);
        } catch (Exception e) {
    
            log.error("docToHtmlText 异常", e);
        } finally {
    
            baos.close();
            outStream.close();
        }
        return null;
    }

    /**
     * 读取html文件,转成字符串返回给前端
     * 去除换行,以及连续两个空格
     * @param htmlDirPath html文件路径
     * @return
     * @throws IOException
     */
    private static String readHtmlStr(String htmlDirPath) throws IOException {
    
        log.info("处理生成的html,字符串形式给前端:{} ...Start..", htmlDirPath);
        String htmlStr = "";
        try {
    
            Path htmlPath = Paths.get(htmlDirPath);
            htmlStr = new String(Files.readAllBytes(htmlPath));
            htmlStr = htmlStr.replaceAll("\\n", "");
            htmlStr = htmlStr.replaceAll("\\s{2,}", " ");
            log.info("处理生成的html,字符串形式给前端。。。end");
        } catch (IOException e) {
    
            log.error("处理生成的html,字符串形式出错了, {}", e.getMessage());
        }
        return htmlStr;
    }
}

6.后端配置文件

代码如下:

spring.application.name=ue
server.port=8000

##UE编辑器配置
#编辑器访问服务器的图片地址
ue.showpath=http://localhost:8000/resource
#ue文件存储路径前缀
ue.savepath=/Users/cookie/Documents/coding/uedemo

!!! ue.showpath=生产上有nginx需要在nginx.conf进行配置

在这里插入图片描述

三、实现效果

---

总结

赠人玫瑰,手留余香
源码地址:
https://gitee.com/gwancookie/uedemo

读取word文档生成html借鉴:
https://blog.csdn.net/qq_44717657/article/details/124497326

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_51547113/article/details/137396271

智能推荐

使用nginx解决浏览器跨域问题_nginx不停的xhr-程序员宅基地

文章浏览阅读1k次。通过使用ajax方法跨域请求是浏览器所不允许的,浏览器出于安全考虑是禁止的。警告信息如下:不过jQuery对跨域问题也有解决方案,使用jsonp的方式解决,方法如下:$.ajax({ async:false, url: 'http://www.mysite.com/demo.do', // 跨域URL ty..._nginx不停的xhr

在 Oracle 中配置 extproc 以访问 ST_Geometry-程序员宅基地

文章浏览阅读2k次。关于在 Oracle 中配置 extproc 以访问 ST_Geometry,也就是我们所说的 使用空间SQL 的方法,官方文档链接如下。http://desktop.arcgis.com/zh-cn/arcmap/latest/manage-data/gdbs-in-oracle/configure-oracle-extproc.htm其实简单总结一下,主要就分为以下几个步骤。..._extproc

Linux C++ gbk转为utf-8_linux c++ gbk->utf8-程序员宅基地

文章浏览阅读1.5w次。linux下没有上面的两个函数,需要使用函数 mbstowcs和wcstombsmbstowcs将多字节编码转换为宽字节编码wcstombs将宽字节编码转换为多字节编码这两个函数,转换过程中受到系统编码类型的影响,需要通过设置来设定转换前和转换后的编码类型。通过函数setlocale进行系统编码的设置。linux下输入命名locale -a查看系统支持的编码_linux c++ gbk->utf8

IMP-00009: 导出文件异常结束-程序员宅基地

文章浏览阅读750次。今天准备从生产库向测试库进行数据导入,结果在imp导入的时候遇到“ IMP-00009:导出文件异常结束” 错误,google一下,发现可能有如下原因导致imp的数据太大,没有写buffer和commit两个数据库字符集不同从低版本exp的dmp文件,向高版本imp导出的dmp文件出错传输dmp文件时,文件损坏解决办法:imp时指定..._imp-00009导出文件异常结束

python程序员需要深入掌握的技能_Python用数据说明程序员需要掌握的技能-程序员宅基地

文章浏览阅读143次。当下是一个大数据的时代,各个行业都离不开数据的支持。因此,网络爬虫就应运而生。网络爬虫当下最为火热的是Python,Python开发爬虫相对简单,而且功能库相当完善,力压众多开发语言。本次教程我们爬取前程无忧的招聘信息来分析Python程序员需要掌握那些编程技术。首先在谷歌浏览器打开前程无忧的首页,按F12打开浏览器的开发者工具。浏览器开发者工具是用于捕捉网站的请求信息,通过分析请求信息可以了解请..._初级python程序员能力要求

Spring @Service生成bean名称的规则(当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致)_@service beanname-程序员宅基地

文章浏览阅读7.6k次,点赞2次,收藏6次。@Service标注的bean,类名:ABDemoService查看源码后发现,原来是经过一个特殊处理:当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致public class AnnotationBeanNameGenerator implements BeanNameGenerator { private static final String C..._@service beanname

随便推点

二叉树的各种创建方法_二叉树的建立-程序员宅基地

文章浏览阅读6.9w次,点赞73次,收藏463次。1.前序创建#include&lt;stdio.h&gt;#include&lt;string.h&gt;#include&lt;stdlib.h&gt;#include&lt;malloc.h&gt;#include&lt;iostream&gt;#include&lt;stack&gt;#include&lt;queue&gt;using namespace std;typed_二叉树的建立

解决asp.net导出excel时中文文件名乱码_asp.net utf8 导出中文字符乱码-程序员宅基地

文章浏览阅读7.1k次。在Asp.net上使用Excel导出功能,如果文件名出现中文,便会以乱码视之。 解决方法: fileName = HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8);_asp.net utf8 导出中文字符乱码

笔记-编译原理-实验一-词法分析器设计_对pl/0作以下修改扩充。增加单词-程序员宅基地

文章浏览阅读2.1k次,点赞4次,收藏23次。第一次实验 词法分析实验报告设计思想词法分析的主要任务是根据文法的词汇表以及对应约定的编码进行一定的识别,找出文件中所有的合法的单词,并给出一定的信息作为最后的结果,用于后续语法分析程序的使用;本实验针对 PL/0 语言 的文法、词汇表编写一个词法分析程序,对于每个单词根据词汇表输出: (单词种类, 单词的值) 二元对。词汇表:种别编码单词符号助记符0beginb..._对pl/0作以下修改扩充。增加单词

android adb shell 权限,android adb shell权限被拒绝-程序员宅基地

文章浏览阅读773次。我在使用adb.exe时遇到了麻烦.我想使用与bash相同的adb.exe shell提示符,所以我决定更改默认的bash二进制文件(当然二进制文件是交叉编译的,一切都很完美)更改bash二进制文件遵循以下顺序> adb remount> adb push bash / system / bin /> adb shell> cd / system / bin> chm..._adb shell mv 权限

投影仪-相机标定_相机-投影仪标定-程序员宅基地

文章浏览阅读6.8k次,点赞12次,收藏125次。1. 单目相机标定引言相机标定已经研究多年,标定的算法可以分为基于摄影测量的标定和自标定。其中,应用最为广泛的还是张正友标定法。这是一种简单灵活、高鲁棒性、低成本的相机标定算法。仅需要一台相机和一块平面标定板构建相机标定系统,在标定过程中,相机拍摄多个角度下(至少两个角度,推荐10~20个角度)的标定板图像(相机和标定板都可以移动),即可对相机的内外参数进行标定。下面介绍张氏标定法(以下也这么称呼)的原理。原理相机模型和单应矩阵相机标定,就是对相机的内外参数进行计算的过程,从而得到物体到图像的投影_相机-投影仪标定

Wayland架构、渲染、硬件支持-程序员宅基地

文章浏览阅读2.2k次。文章目录Wayland 架构Wayland 渲染Wayland的 硬件支持简 述: 翻译一篇关于和 wayland 有关的技术文章, 其英文标题为Wayland Architecture .Wayland 架构若是想要更好的理解 Wayland 架构及其与 X (X11 or X Window System) 结构;一种很好的方法是将事件从输入设备就开始跟踪, 查看期间所有的屏幕上出现的变化。这就是我们现在对 X 的理解。 内核是从一个输入设备中获取一个事件,并通过 evdev 输入_wayland

推荐文章

热门文章

相关标签