Java多线程方式快速解析大量文本内容得到pdf链接转换为文本-学习笔记

Java多线程方式快速解析大量文本内容得到pdf链接转换为文本-学习笔记

解析流程:

1、一个目录里面包含大量多种格式文件;
2、从目录中提取txt为后缀的文件路径List;
3、根据服务器性能设定多线程处理文本数量;
4、txt文本中获取所有的链接;
5、通过正则提取后缀为.pdf链接;
6、下载pdf文件到本地;
7、使用开源工具把pdf转换为txt内容;


获取链接正则表达式

//URL正则
private static final Pattern WEB_URL = Pattern.compile(
            "((?:(http|https|Http|Https):\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?((?:(?:[a-zA-Z0-9\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF][a-zA-Z0-9\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF\\-]{0,64}\\.)+(?:(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(?:biz|b[abdefghijmnorstvwyz])|(?:cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(?:edu|e[cegrstu])|f[ijkmor]|(?:gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(?:info|int|i[delmnoqrst])|(?:jobs|j[emop])|k[eghimnprwyz]|l[abcikrstuvy]|(?:mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])|(?:name|net|n[acefgilopruz])|(?:org|om)|(?:pro|p[aefghklmnrstwy])|qa|r[eosuw]|s[abcdeghijklmnortuvyz]|(?:tel|travel|t[cdfghjklmnoprtvwz])|u[agksyz]|v[aceginu]|w[fs]|(?:xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-80akhbyknj4f|xn\\-\\-9t4b11yi5a|xn\\-\\-deba0ad|xn\\-\\-g6w251d|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-zckzah)|y[etu]|z[amw]))|(?:(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])))(?:\\:\\d{1,5})?)(\\/(?:(?:[a-zA-Z0-9\\;\\/\\?\\:\\@\\&\\=\\#\\~\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?(?:\\b|$)");

解析PDF为txt需要用到工具添加到pom文件

<!-- PDF识别为txt内容pom -->
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.13</version>
</dependency>

PDF转换为txt工具类:

package com.utils;

import java.io.IOException;

import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;
import com.itextpdf.text.pdf.parser.SimpleTextExtractionStrategy;
import com.itextpdf.text.pdf.parser.TextExtractionStrategy;

public class PdfToTextFileUtil {
    /**
     * 将PDF文件分页解析为txt格式文件
     * 
     * @param fileName
     * @throws IOException
     */
    public static String getPdfFileText(String fileName) throws IOException {
        StringBuilder sf = new StringBuilder();
        PdfReader reader = new PdfReader(fileName);
        PdfReaderContentParser parser = new PdfReaderContentParser(reader);
        TextExtractionStrategy strategy = null;
        //PDF每页解析的内容,再追加
        for (int i = 0; i < reader.getNumberOfPages(); i++) {
            strategy = parser.processContent(i+1, new SimpleTextExtractionStrategy());
            sf.append(strategy.getResultantText().toString());
        }
        return sf.toString();
    }

    public static void main(String[] args) {
        String fileName = "C:/Users/13533/Desktop/image/1.pdf";
        System.out.println(getPdfFileText(fileName));
    }
}

用到的一些实体类

public class PrivacyPolicyTextInfo {
       public String fileName;
       public String content;

       public PrivacyPolicyTextInfo(String fileName, String content) {
            this.fileName = fileName;
            this.content = content;
       }
}

文件目录中获取为.txt后缀的文件路径代码

public class CommonUtil {
    /**
     * 获取目录下给定文件后缀的所有文件路径
     *
     * @param dir       需要搜索的目录
     * @param endkeys   需要搜索的文件后缀类型,若为null,则返回所有文件
     * @param recursion 是否递归搜索,false不递归搜索,true递归搜索
     * @return 返回所有搜索到的文件路径
     */
    public static List<String> listAllFilesInDir(String dir, String[] endkeys, boolean recursion) {
        List<String> result = new ArrayList<String>();
        File[] files = new File(dir).listFiles();
        if (null != files && files.length > 0) {
            for (File file : files) {
                if (file.isDirectory()) {
                    if (recursion)
                        result.addAll(listAllFilesInDir(file.getAbsolutePath(), endkeys, recursion));// 若为目录,则递归搜索
                } else if (null != endkeys) {
                    String temp = file.getName();
                    for (String endkey : endkeys)
                        if (temp.endsWith(endkey))
                            result.add(file.getAbsolutePath().replaceAll("\\\\", "/"));// 若为给定类型,则获取绝对路径并加入结果链表
                } else
                    result.add(file.getAbsolutePath().replaceAll("\\\\", "/"));// fileTypes为null,则将所有类型文件加入结果链表
            }
        }
        return result;// 返回结果
    }
}

并多线程方式从txt内容中通过正则表达式获取链接地址,判断是否是.pdf后缀链接

package com.utils;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;

import com.entity.PrivacyPolicyTextInfo;

public class URLTokenizer {

    //获取URL正则
    private static final Pattern WEB_URL = Pattern.compile(
            "((?:(http|https|Http|Https):\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?((?:(?:[a-zA-Z0-9\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF][a-zA-Z0-9\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF\\-]{0,64}\\.)+(?:(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(?:biz|b[abdefghijmnorstvwyz])|(?:cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(?:edu|e[cegrstu])|f[ijkmor]|(?:gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(?:info|int|i[delmnoqrst])|(?:jobs|j[emop])|k[eghimnprwyz]|l[abcikrstuvy]|(?:mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])|(?:name|net|n[acefgilopruz])|(?:org|om)|(?:pro|p[aefghklmnrstwy])|qa|r[eosuw]|s[abcdeghijklmnortuvyz]|(?:tel|travel|t[cdfghjklmnoprtvwz])|u[agksyz]|v[aceginu]|w[fs]|(?:xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-80akhbyknj4f|xn\\-\\-9t4b11yi5a|xn\\-\\-deba0ad|xn\\-\\-g6w251d|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-zckzah)|y[etu]|z[amw]))|(?:(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])))(?:\\:\\d{1,5})?)(\\/(?:(?:[a-zA-Z0-9\\;\\/\\?\\:\\@\\&\\=\\#\\~\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?(?:\\b|$)");

    public static List<String> segment(String text) {
        List<String> termList = new LinkedList<String>();
        Matcher matcher = WEB_URL.matcher(text);
        while (matcher.find()) {
            String machUrl = matcher.group();
            if(machUrl==null){
                continue;
            }
            if(!machUrl.toLowerCase().startsWith("http") || !machUrl.toLowerCase().endsWith(".pdf")) {
                continue;
            }
            termList.add(machUrl);
        }
        return termList;
    }

    public static List<String> threadSegment(List<String> list) throws InterruptedException, ExecutionException{
        List<String> newList = new ArrayList<String>();
        // 每10条数据开启一条线程
        int threadSize = 10;
        // 总数据条数
        int dataSize = list.size();
        // 线程数
        int threadNum = dataSize / threadSize + 1;
        // 定义标记,过滤threadNum为整数
        boolean special = dataSize % threadSize == 0;

        // 创建一个线程池
        ExecutorService exec = Executors.newFixedThreadPool(threadNum);
        // 定义一个任务集合
        List<Callable<List<String>>> tasks = new ArrayList<Callable<List<String>>>();
        Callable<List<String>> task = null;
        List<String> cutList = null;

        // 确定每条线程的数据
        for (int i = 0; i < threadNum; i++) {
            if (i == threadNum - 1) {
                if (special) {
                    break;
                }
                cutList = list.subList(threadSize * i, dataSize);
            } else {
                cutList = list.subList(threadSize * i, threadSize * (i + 1));
            }

            final List<String> listStr = cutList;
            task = new Callable<List<String>>() {
                @Override
                public List<String> call() throws Exception {
//                    System.out.println(Thread.currentThread().getName() + "线程:" + listStr);
                    List<String> res = new ArrayList<>();
                    listStr.forEach(path->{
                        try {
                            List<String> termList = segment(Text2Pic.readTxtFile(path));
                            if(termList!=null && termList.size()>0) {
                                res.addAll(termList);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    });
                    return res;
                }
            };
            tasks.add(task);
        }

        List<Future<List<String>>> results = exec.invokeAll(tasks);

        for (Future<List<String>> future : results) {
            newList.addAll(future.get());
        }
        // 关闭线程池
        exec.shutdown();
        return newList;
    }

    //解析是否存在PDF隐私政策链接
    private static void pdfPrivacyContent(String uncompress, List<PrivacyPolicyTextInfo> subPagePrivacyDetailList) throws IOException{
        List<String> filePaths = CommonUtil.listAllFilesInDir(uncompress  + File.separator + "capture_info", new String[]{".txt",".TXT"}, true);
        if(filePaths==null || filePaths.size()==0) {
            return;
        }
        long t1 = System.currentTimeMillis();
        List<String> list = null;
        try {
            //得到PDF链接地址
            list = URLTokenizer.threadSegment(filePaths);
            System.out.println(list);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        if(list==null || list.size()==0) {
            return ;
        }

        for (int i = 0; i < list.size(); i++) {
            //识别PDF内容
            String url = list.get(i);
            String fileName = url.substring(url.lastIndexOf("/")+1, url.length());
            String pdfLoalPath = uncompress  + File.separator + fileName;
            FileUtils.copyURLToFile(new URL(list.get(i)), new File(pdfLoalPath));
            if(!new File(pdfLoalPath).exists()) {
                continue;
            }
            String privacyContent = PdfToTextFileUtil.getPdfFileText(pdfLoalPath);
            if(StringUtils.isBlank(privacyContent)) {
                continue;
            }

            if (!privacyContent.contains("隐私政策") || privacyContent.length() < 200) {
                continue;
            }
            PrivacyPolicyTextInfo info = new PrivacyPolicyTextInfo(fileName,privacyContent);
            subPagePrivacyDetailList.add(info);
        }
        long t2 = System.currentTimeMillis();
        System.out.print("识别耗时:"+(t2-t1));
    }

    public static void main(String[] args) {
//      String txtPath = "C:/Users/13533/Downloads/且慢_20220422094601/205f0b6c85faa32e5bce73c24cfa1b77_26605_AUTO/capture_info/";
//      List<String> filePaths = CommonUtil.listAllFilesInDir(txtPath, new String[]{".txt",".TXT"}, true);
//      if(filePaths==null || filePaths.size()==0) {
//          return;
//      }
//      long t1 = System.currentTimeMillis();
//      try {
//          List<String> list = threadSegment(filePaths);
//          System.out.println(list);
//      } catch (InterruptedException e) {
//          e.printStackTrace();
//      } catch (ExecutionException e) {
//          e.printStackTrace();
//      }
//      
//      long t2 = System.currentTimeMillis();
//      System.out.println("识别耗时:"+(t2-t1));

        String txtPath = "C:/Users/13533/Downloads/且慢_20220422094601/205f0b6c85faa32e5bce73c24cfa1b77_26605_AUTO/";
        List<PrivacyPolicyTextInfo> list = new ArrayList<>();
        try {
            pdfPrivacyContent(txtPath, list);
        } catch (IOException e) {
            e.printStackTrace();
        }

        if(list!=null) {
            for (PrivacyPolicyTextInfo privacyPolicyTextInfo : list) {
                System.out.println(privacyPolicyTextInfo.content);
            }
        }
    }
}

执行后得到内容:

如果有什么好的建议,可以在下面留言评论,一起相互学习下。

发布者:小站,转转请注明出处:http://blog.gzcity.top/4176.html

(1)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022年5月1日 20:53
下一篇 2022年5月3日 02:49

相关推荐

  • WebLogic中间件任意命令执行漏洞。

    一、背景简介 Weblogic是一款商用中间件应用服务器产品,可以为应用程序提供运行访问环境。 二、漏洞详情 公开日期:2022-07-29漏洞编号:暂无危害等级:高危漏洞描述:由于没有过滤危险字符,导致攻击者可以对T3/IIOP接口发送恶意内容,执行任意命令。 三、影响版本 未知 四、处置情况 1.暴露在公网的WebLogic应配置对外禁用T3和IIOP,…

    2022年8月3日
    3.2K8470
  • 查看apk安装包的miniSdkVersion、targetSdkVersion

    方式一:命令: aapt list -a *.apk | grep SdkVersion用法例如:显示的结果为16进制,需要自己转换成 10进制。 查看apk安装包的miniSdkVersion、targetSdkVersion 方式二:命令: aapt dump badging .apk如果觉得结果集太长了,可以加grep过滤一下: aapt dump b…

    2022年12月9日
    5.3K13340
  • Java操作SFTP工具类,文件上传下载删除,获取列表目录

    Java操作SFTP工具类,文件上传下载删除,获取列表目录 需要依赖的Maven包 <!– SFTP –> <dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>…

    2022年6月1日
    827770
  • chrome怎么导入证书 chrome导入证书的图文步骤

    我们在使用谷歌浏览器时,有时需要导入证书,但是很多人不知道怎么操作,那么Google浏览器怎么导入证书呢,下面本文就介绍一下。 我的Chrome的版本是 1.首先,打开电脑上面的Google之后,点击浏览器右上角的“三个点”按钮,如图所示。 2.然后选择下拉菜单中的“设置”,进入Google的系统设置,如图所示。 3.进入Google的设置之后,点击&quo…

    2022年9月13日
    23210
  • 微信小程序在Android、iOS、Windows、MacOS的文件存放路径

    一、微信小程序文件存放路径 /data/data/com.tencent.mm/MicroMsg/{{user哈希值}}/appbrand/pkg/ iOS越狱:/User/Containers/Data/Application/{{系统UUID}}/Library/WechatPrivate/{{user哈希值}}/WeApp/LocalCache/rel…

    学习笔记 2022年12月4日
    3.9K320

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

评论列表(977条)