来源: nodejs将PDF文件转换成txt文本,并利用python处理转换后的文本文件 – Boom__Clap – 博客园
目前公司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']}
Mikel
