zoukankan      html  css  js  c++  java
  • nodejs将PDF文件转换成txt文本,并利用python处理转换后的文本文件

    目前公司Web服务端的开发是用Nodejs,所以开发功能的话首先使用Nodejs,这也是为什么不直接用python转换的原因。

    由于node对文本的处理(提取所需信息)的能力不强,类似于npm上的包:‘linebyline’、'lineReader',处理能力都不强,所以使用python来处理。

    目的:提取PDF中带有‘检查'字样的文本(行)

    思路:

    1、Nodejs 找到PDF转换text的包,转换,将text文本信息发送到Python服务器。

    2、创建一个简单的Python服务器,接收并处理text文本,得到所需要的文本信息,打包成Json并发送到Node服务端。

    3、Node服务端接收到后,再发给前端页面将信息展示。

     

    好,那首先我们要去npm官网上找到转换用的包,pdf-textstring是一个不错的包,测试之后,大部分PDF都可以成功转换成text文本,但是有个别文件转换不成功,所以还需要换一个,最后是使用了'pdf2json'这个包,在npm 上找包,有一个要点,就是包名很短,功能很多,类似的处理功能会集中在某个包上,但是包名可能只是其中一种功能。

    PDF文件样本:

    转换代码:

     var fs = require('fs'),
         PDFParser = require("pdf2json");
    
     var pdfParser = new PDFParser(this, 1);
    pdfParser.loadPDF("tmp/testpdf.pdf");
    pdfParser.on("pdfParser_dataError", errData => console.error(errData.parserError)); pdfParser.on("pdfParser_dataReady", pdfData => {
    data =
    pdfParser.getRawTextContent()
         console.log(‘文本信息:’+data)
     });

    转换后的文本信息:

    操作任务: 3号主变压器带10kVB、C母全部负荷,2号主变压器停电,2号主变压器、162-2隔 
     
     
     
    离开关、170、802断路器由运行状态转换为检修状态,110kVB母由运行状态转换为检修状态 
     
     
     
    顺序 操 作 项 目 √ 时间 
    1 投入10kVB、C母分段820闭锁备自投压板   
    2 退出10kVB、C母分段820备投跳803压板   
    3 退出10kVB、C母分段820备投合820压板   
    4 检查2、3号主变压器分头位置一致   
    5 合上820断路器   
    6 检查820断路器确带负荷   
    7 检查2号、3号主变压器负荷分配正常   
    8 拉开802断路器   
    9 检查802断路器在分闸位置   
    10 检查3号主变压器不过负荷   
    11 合上12中0中性点接地刀闸   
    12 检查12中0中性点接地刀闸在合闸位置   
    13 检查802断路器在分闸位置   
    14 将802-3手车由运行位置拉至试验位置   
    15 检查802-3手车到位指示正确   
    16 将802手车由运行位置拉至试验位置

    Node服务端将转换后的文本信息发送到Python服务端:

    //Node发送数据并接受返回的处理后的数据

    PDFPARSER(data, function(err, result) {
    var test = unescape(result.replace(/\\u/g, '%u'))//解python端传来的unicode
    res.send(ERRCODE.MakeResult(ERRCODE.OK, JSON.parse(test)));//JSON.parse一次,将解后的字符串换转成Json,发给前端
    return;

    });

    //发送数据的函数

    var PDFPARSER = function (reqData, callback) {
        var buf = new BUFFER.Buffer(reqData);
        var op = {
            host: "127.0.0.1",
            port: 8087,
            method: 'POST',
            path: "/",
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
                'Content-Length': buf.length
            }
        };
    
        var req = HTTP.request(op, function (res) {
            var recvData = "";
    
            res.on('data', function (chunk) {
                recvData += chunk.toString();
            });
    
            res.on('end', function () {
    
                if (callback) {
                    callback(null, recvData);
                }
    
            });
        });
    
        req.on('error', function (e) {
            console.log(e);
        });
    
        req.write(reqData);
    
        req.end();
    };

    Python服务端接受并处理、返还数据:

    import sys 
    import codecs
    import SimpleHTTPServer
    import SocketServer
    import json
    import re
    from urlparse import urlparse
    from urlparse import parse_qs
    
    PORT = 8087
    
    class Handler(SimpleHTTPServer.SimpleHTTPRequestHandler):
        def do_GET(self):
            pass#print self.headers
            
        def do_POST(self):
            #print self.headers
            
            contentLength = int(self.headers["Content-Length"])
    
            textString = self.rfile.read(contentLength)
            s = textString.split("\n")
    
            test = []
            for fileLine in s:
                if u'检查' in fileLine:
                    line_pattern =r'\s*\d+\s?(.*)'
            
                    def func(text):
                        c = re.compile(line_pattern)
                        lists = []
                        lines = text.split('\n')
                        for line in lines:
                            r = c.findall(line)
                            if r:
                                lists.append(r[0])
            
                        return '\n'.join(lists)
            
                    
                    result = func(fileLine)
                    test.append(result)
            print test
                    
            self.send_response(200)
            self.send_header('Content-type','text/plain')
            self.end_headers()
            #print result.decode("utf-8")
            #print result
            test = {"CZBZ": test}
    #这里test的格式是因为前端页面接收数据的格式需要
            self.wfile.write(json.dumps(test) )
                    
            
    
            
    
    
    
    if __name__ == "__main__":
        reload(sys)
        sys.setdefaultencoding("utf-8")
        httpd = SocketServer.TCPServer(("", PORT), Handler)
        print "serving at port", PORT
        httpd.serve_forever()

     Python处理后的数据:

    {"CZBZ":['\xe6\xa3\x80\xe6\x9f\xa52\xe3\x80\x813\xe5\x8f\xb7\xe4\xb8\xbb\xe5\x8f\x98\xe5\x8e\x8b\xe5\x99\xa8\xe5\x88\x86\xe5\xa4\xb4\xe4\xbd\x8d\xe7\xbd\xae\xe4\xb8\x80\xe8\x87\xb4   \r', '\xe6\xa3\x80\xe6\x9f\xa5820\xe6\x96\xad\xe8\xb7\xaf\xe5\x99\xa8\xe7\xa1\xae\xe5\xb8\xa6\xe8\xb4\x9f\xe8\x8d\xb7   \r', '\xe6\xa3\x80\xe6\x9f\xa52\xe5\x8f\xb7\xe3\x80\x813\xe5\x8f\xb7\xe4\xb8\xbb\xe5\x8f\x98\xe5\x8e\x8b\xe5\x99\xa8\xe8\xb4\x9f\xe8\x8d\xb7\xe5\x88\x86\xe9\x85\x8d\xe6\xad\xa3\xe5\xb8\xb8   \r', '\xe6\xa3\x80\xe6\x9f\xa5802\xe6\x96\xad\xe8\xb7\xaf\xe5\x99\xa8\xe5\x9c\xa8\xe5\x88\x86\xe9\x97\xb8\xe4\xbd\x8d\xe7\xbd\xae   \r', '\xe6\xa3\x80\xe6\x9f\xa53\xe5\x8f\xb7\xe4\xb8\xbb\xe5\x8f\x98\xe5\x8e\x8b\xe5\x99\xa8\xe4\xb8\x8d\xe8\xbf\x87\xe8\xb4\x9f\xe8\x8d\xb7   \r', '\xe6\xa3\x80\xe6\x9f\xa512\xe4\xb8\xad0\xe4\xb8\xad\xe6\x80\xa7\xe7\x82\xb9\xe6\x8e\xa5\xe5\x9c\xb0\xe5\x88\x80\xe9\x97\xb8\xe5\x9c\xa8\xe5\x90\x88\xe9\x97\xb8\xe4\xbd\x8d\xe7\xbd\xae   \r', '\xe6\xa3\x80\xe6\x9f\xa5802\xe6\x96\xad\xe8\xb7\xaf\xe5\x99\xa8\xe5\x9c\xa8\xe5\x88\x86\xe9\x97\xb8\xe4\xbd\x8d\xe7\xbd\xae   \r', '\xe6\xa3\x80\xe6\x9f\xa5802-3\xe6\x89\x8b\xe8\xbd\xa6\xe5\x88\xb0\xe4\xbd\x8d\xe6\x8c\x87\xe7\xa4\xba\xe6\xad\xa3\xe7\xa1\xae   \r', '\xe6\xa3\x80\xe6\x9f\xa5802\xe6\x89\x8b\xe8\xbd\xa6\xe5\x88\xb0\xe4\xbd\x8d\xe6\x8c\x87\xe7\xa4\xba\xe6\xad\xa3\xe7\xa1\xae   \r', '\xe6\xa3\x80\xe6\x9f\xa5170\xe6\x96\xad\xe8\xb7\xaf\xe5\x99\xa8\xe5\x9c\xa8\xe5\x88\x86\xe9\x97\xb8\xe4\xbd\x8d\xe7\xbd\xae   \r', '\xe6\xa3\x80\xe6\x9f\xa5170-2\xe9\x9a\x94\xe7\xa6\xbb\xe5\xbc\x80\xe5\x85\xb3\xe5\x9c\xa8\xe5\x88\x86\xe9\x97\xb8\xe4\xbd\x8d\xe7\xbd\xae   \r', '\xe6\xa3\x80\xe6\x9f\xa5170-3\xe9\x9a\x94\xe7\xa6\xbb\xe5\xbc\x80\xe5\x85\xb3\xe5\x9c\xa8\xe5\x88\x86\xe9\x97\xb8\xe4\xbd\x8d\xe7\xbd\xae   \r', '\xe6\xa3\x80\xe6\x9f\xa5162-3\xe9\x9a\x94\xe7\xa6\xbb\xe5\xbc\x80\xe5\x85\xb3\xe5\x9c\xa8\xe5\x88\x86\xe9\x97\xb8\xe4\xbd\x8d\xe7\xbd\xae   \r', '\xe6\xa3\x80\xe6\x9f\xa5162-2\xe9\x9a\x94\xe7\xa6\xbb\xe5\xbc\x80\xe5\x85\xb3\xe5\x9c\xa8\xe5\x88\x86\xe9\x97\xb8\xe4\xbd\x8d\xe7\xbd\xae   \r', '\xe6\xa3\x80\xe6\x9f\xa5170-2\xe9\x9a\x94\xe7\xa6\xbb\xe5\xbc\x80\xe5\x85\xb3\xe5\x9c\xa8\xe5\x88\x86\xe9\x97\xb8\xe4\xbd\x8d\xe7\xbd\xae   \r', '\xe6\xa3\x80\xe6\x9f\xa5170-20\xe6\x8e\xa5\xe5\x9c\xb0\xe5\x88\x80\xe9\x97\xb8\xe5\x9c\xa8\xe5\x90\x88\xe9\x97\xb8\xe4\xbd\x8d\xe7\xbd\xae   \r', '\xe6\xa3\x80\xe6\x9f\xa5170-3\xe9\x9a\x94\xe7\xa6\xbb\xe5\xbc\x80\xe5\x85\xb3\xe5\x9c\xa8\xe5\x88\x86\xe9\x97\xb8\xe4\xbd\x8d\xe7\xbd\xae   \r', '\xe6\xa3\x80\xe6\x9f\xa5170-30\xe6\x8e\xa5\xe5\x9c\xb0\xe5\x88\x80\xe9\x97\xb8\xe5\x9c\xa8\xe5\x90\x88\xe9\x97\xb8\xe4\xbd\x8d\xe7\xbd\xae   \r', '\xe6\xa3\x80\xe6\x9f\xa51B9\xe9\x9a\x94\xe7\xa6\xbb\xe5\xbc\x80\xe5\x85\xb3\xe5\x9c\xa8\xe5\x88\x86\xe9\x97\xb8\xe4\xbd\x8d\xe7\xbd\xae   \r', '\xe6\xa3\x80\xe6\x9f\xa51B90\xe6\x8e\xa5\xe5\x9c\xb0\xe5\x88\x80\xe9\x97\xb8\xe5\x9c\xa8\xe5\x90\x88\xe9\x97\xb8\xe4\xbd\x8d\xe7\xbd\xae   \r', '\xe6\xa3\x80\xe6\x9f\xa5162-2\xe9\x9a\x94\xe7\xa6\xbb\xe5\xbc\x80\xe5\x85\xb3\xe5\x9c\xa8\xe5\x88\x86\xe9\x97\xb8\xe4\xbd\x8d\xe7\xbd\xae   \r', '\xe6\xa3\x80\xe6\x9f\xa51B10\xe6\x8e\xa5\xe5\x9c\xb0\xe5\x88\x80\xe9\x97\xb8\xe5\x9c\xa8\xe5\x90\x88\xe9\x97\xb8\xe4\xbd\x8d\xe7\xbd\xae   \r']}
  • 相关阅读:
    QStringLiteral(源代码里有一个通过构造函数产生的从const char*到QString的隐式转换,QStringLiteral字符串可以放在代码的任何地方,编译期直接生成utf16字符串,速度很快,体积变大)
    utf8格式源代码中的字符串,默认都会当作char来处理,除非用L""符号来修饰
    Qt Installer Framework的学习
    发布Qt Quick桌面应用程序的方法
    先对数组排序,在进行折半查找(C++)
    7个高效习惯
    人活着是靠精神(几个例子都是我自己发现的)
    VC++对象布局的奥秘:虚函数、多继承、虚拟继承
    delphi数字签名验证及能够获取数字签名文件信息(利用wintrust.dll的导出函数,翻译一下)
    算法系列之二十:计算中国农历(二)
  • 原文地址:https://www.cnblogs.com/yourstars/p/5893244.html
Copyright © 2011-2022 走看看