क्या पीडीएफ फाइलों को पाठ में बदलने के लिए कोई अजगर मॉड्यूल है? मैंने एक्टिविस्टेट में पाए गए एक टुकड़े के कोड की कोशिश की, जो pypdf का उपयोग करता है, लेकिन उत्पन्न टेक्स्ट में कोई जगह नहीं थी और कोई फायदा नहीं था।
क्या पीडीएफ फाइलों को पाठ में बदलने के लिए कोई अजगर मॉड्यूल है? मैंने एक्टिविस्टेट में पाए गए एक टुकड़े के कोड की कोशिश की, जो pypdf का उपयोग करता है, लेकिन उत्पन्न टेक्स्ट में कोई जगह नहीं थी और कोई फायदा नहीं था।
जवाबों:
PDFMiner का प्रयास करें । यह HTML, SGML या "टैग की गई PDF" प्रारूप के रूप में पीडीएफ फाइलों से पाठ निकाल सकता है।
टैग किए गए पीडीएफ प्रारूप सबसे साफ लगता है, और एक्सएमएल टैग को छीनकर सिर्फ नंगे पाठ को छोड़ दिया जाता है।
पायथन 3 संस्करण के तहत उपलब्ध है:
PDFMiner के बाद से पैकेज बदल गया है codeape तैनात।
EDIT (फिर से):
PDFMiner संस्करण में फिर से अपडेट किया गया है 20100213
आप निम्न के साथ इंस्टॉल किए गए संस्करण की जांच कर सकते हैं:
>>> import pdfminer
>>> pdfminer.__version__
'20100213'
यहां अपडेट किया गया संस्करण है (जो मैंने बदल / जोड़ा है उस पर टिप्पणियों के साथ):
def pdf_to_csv(filename):
from cStringIO import StringIO #<-- added so you can copy/paste this to try it
from pdfminer.converter import LTTextItem, TextConverter
from pdfminer.pdfparser import PDFDocument, PDFParser
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
class CsvConverter(TextConverter):
def __init__(self, *args, **kwargs):
TextConverter.__init__(self, *args, **kwargs)
def end_page(self, i):
from collections import defaultdict
lines = defaultdict(lambda : {})
for child in self.cur_item.objs:
if isinstance(child, LTTextItem):
(_,_,x,y) = child.bbox #<-- changed
line = lines[int(-y)]
line[x] = child.text.encode(self.codec) #<-- changed
for y in sorted(lines.keys()):
line = lines[y]
self.outfp.write(";".join(line[x] for x in sorted(line.keys())))
self.outfp.write("\n")
# ... the following part of the code is a remix of the
# convert() function in the pdfminer/tools/pdf2text module
rsrc = PDFResourceManager()
outfp = StringIO()
device = CsvConverter(rsrc, outfp, codec="utf-8") #<-- changed
# becuase my test documents are utf-8 (note: utf-8 is the default codec)
doc = PDFDocument()
fp = open(filename, 'rb')
parser = PDFParser(fp) #<-- changed
parser.set_document(doc) #<-- added
doc.set_parser(parser) #<-- added
doc.initialize('')
interpreter = PDFPageInterpreter(rsrc, device)
for i, page in enumerate(doc.get_pages()):
outfp.write("START PAGE %d\n" % i)
interpreter.process_page(page)
outfp.write("END PAGE %d\n" % i)
device.close()
fp.close()
return outfp.getvalue()
संपादित करें (अभी तक फिर से):
यहाँ में नवीनतम संस्करण के लिए एक अद्यतन है pypi , 20100619p1
। संक्षेप में मैं बदल दिया LTTextItem
साथ LTChar
और CsvConverter निर्माता को LAParams का एक उदाहरण पारित कर दिया।
def pdf_to_csv(filename):
from cStringIO import StringIO
from pdfminer.converter import LTChar, TextConverter #<-- changed
from pdfminer.layout import LAParams
from pdfminer.pdfparser import PDFDocument, PDFParser
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
class CsvConverter(TextConverter):
def __init__(self, *args, **kwargs):
TextConverter.__init__(self, *args, **kwargs)
def end_page(self, i):
from collections import defaultdict
lines = defaultdict(lambda : {})
for child in self.cur_item.objs:
if isinstance(child, LTChar): #<-- changed
(_,_,x,y) = child.bbox
line = lines[int(-y)]
line[x] = child.text.encode(self.codec)
for y in sorted(lines.keys()):
line = lines[y]
self.outfp.write(";".join(line[x] for x in sorted(line.keys())))
self.outfp.write("\n")
# ... the following part of the code is a remix of the
# convert() function in the pdfminer/tools/pdf2text module
rsrc = PDFResourceManager()
outfp = StringIO()
device = CsvConverter(rsrc, outfp, codec="utf-8", laparams=LAParams()) #<-- changed
# becuase my test documents are utf-8 (note: utf-8 is the default codec)
doc = PDFDocument()
fp = open(filename, 'rb')
parser = PDFParser(fp)
parser.set_document(doc)
doc.set_parser(parser)
doc.initialize('')
interpreter = PDFPageInterpreter(rsrc, device)
for i, page in enumerate(doc.get_pages()):
outfp.write("START PAGE %d\n" % i)
if page is not None:
interpreter.process_page(page)
outfp.write("END PAGE %d\n" % i)
device.close()
fp.close()
return outfp.getvalue()
EDIT (एक बार और):
संस्करण के लिए अद्यतन 20110515
(Oeufcoque Penteano के लिए धन्यवाद!):
def pdf_to_csv(filename):
from cStringIO import StringIO
from pdfminer.converter import LTChar, TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfparser import PDFDocument, PDFParser
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
class CsvConverter(TextConverter):
def __init__(self, *args, **kwargs):
TextConverter.__init__(self, *args, **kwargs)
def end_page(self, i):
from collections import defaultdict
lines = defaultdict(lambda : {})
for child in self.cur_item._objs: #<-- changed
if isinstance(child, LTChar):
(_,_,x,y) = child.bbox
line = lines[int(-y)]
line[x] = child._text.encode(self.codec) #<-- changed
for y in sorted(lines.keys()):
line = lines[y]
self.outfp.write(";".join(line[x] for x in sorted(line.keys())))
self.outfp.write("\n")
# ... the following part of the code is a remix of the
# convert() function in the pdfminer/tools/pdf2text module
rsrc = PDFResourceManager()
outfp = StringIO()
device = CsvConverter(rsrc, outfp, codec="utf-8", laparams=LAParams())
# becuase my test documents are utf-8 (note: utf-8 is the default codec)
doc = PDFDocument()
fp = open(filename, 'rb')
parser = PDFParser(fp)
parser.set_document(doc)
doc.set_parser(parser)
doc.initialize('')
interpreter = PDFPageInterpreter(rsrc, device)
for i, page in enumerate(doc.get_pages()):
outfp.write("START PAGE %d\n" % i)
if page is not None:
interpreter.process_page(page)
outfp.write("END PAGE %d\n" % i)
device.close()
fp.close()
return outfp.getvalue()
LTTextItem
गए हैं LTChar
। unixuser.org/~euske/python/pdfminer/index.html#changes
20110515
आपकी टिप्पणी के अनुसार संस्करण के उत्तर के लिए एक और अनुभाग जोड़ा है ।
चूंकि इन समाधानों में से कोई भी PDFMiner के नवीनतम संस्करण का समर्थन नहीं करता है इसलिए मैंने एक सरल समाधान लिखा है जो PDFMiner का उपयोग करके पीडीएफ का पाठ लौटाएगा। यह उन लोगों के लिए काम करेगा जिनके साथ आयात त्रुटियां हो रही हैंprocess_pdf
import sys
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.pdfpage import PDFPage
from pdfminer.converter import XMLConverter, HTMLConverter, TextConverter
from pdfminer.layout import LAParams
from cStringIO import StringIO
def pdfparser(data):
fp = file(data, 'rb')
rsrcmgr = PDFResourceManager()
retstr = StringIO()
codec = 'utf-8'
laparams = LAParams()
device = TextConverter(rsrcmgr, retstr, codec=codec, laparams=laparams)
# Create a PDF interpreter object.
interpreter = PDFPageInterpreter(rsrcmgr, device)
# Process each page contained in the document.
for page in PDFPage.get_pages(fp):
interpreter.process_page(page)
data = retstr.getvalue()
print data
if __name__ == '__main__':
pdfparser(sys.argv[1])
नीचे दिया गया कोड देखें जो पायथन 3 के लिए काम करता है:
import sys
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.pdfpage import PDFPage
from pdfminer.converter import XMLConverter, HTMLConverter, TextConverter
from pdfminer.layout import LAParams
import io
def pdfparser(data):
fp = open(data, 'rb')
rsrcmgr = PDFResourceManager()
retstr = io.StringIO()
codec = 'utf-8'
laparams = LAParams()
device = TextConverter(rsrcmgr, retstr, codec=codec, laparams=laparams)
# Create a PDF interpreter object.
interpreter = PDFPageInterpreter(rsrcmgr, device)
# Process each page contained in the document.
for page in PDFPage.get_pages(fp):
interpreter.process_page(page)
data = retstr.getvalue()
print(data)
if __name__ == '__main__':
pdfparser(sys.argv[1])
python3
बाद स्पष्ट कोष्ठक के साथ उपयोग करने के लिए print
, किसी को पैकेज से file
कमांड को बदलना open
और आयात करना होगाStringIO
io
Pdftotext एक खुला स्रोत कार्यक्रम (Xpdf का हिस्सा) जिसे आप अजगर से कह सकते हैं (आपने जो मांगा था लेकिन वह उपयोगी हो सकता है)। मैंने इसका उपयोग बिना किसी समस्या के किया है। मुझे लगता है कि Google इसका उपयोग Google डेस्कटॉप में करता है।
-layout
टेक्स्ट को उसी स्थिति में रखने का विकल्प है जैसा कि पीडीएफ में है। अब अगर केवल मैं यह पता लगा सकता हूं कि इसमें पीडीएफ की सामग्री को कैसे पाइप किया जाए।
pdftotext
बहुत अच्छी तरह से काम करने के लिए लगता है, लेकिन इसे एक दूसरे तर्क की आवश्यकता है जो एक हाइफ़न है, अगर आप नतीजों पर परिणाम देखना चाहते हैं।
find . -iname "*.pdf" -exec pdftotext -enc UTF-8 -eol unix -raw {} \;
डिफ़ॉल्ट रूप से उत्पन्न फाइलें मूल नाम को .txt
एक्सटेंशन के साथ ले जाती हैं ।
pyPDF ठीक काम करता है (यह मानते हुए कि आप अच्छी तरह से गठित PDF के साथ काम कर रहे हैं)। यदि आप चाहते हैं कि सभी पाठ (रिक्त स्थान के साथ), आप बस कर सकते हैं:
import pyPdf
pdf = pyPdf.PdfFileReader(open(filename, "rb"))
for page in pdf.pages:
print page.extractText()
आप मेटाडेटा, छवि डेटा और आगे तक आसानी से पहुंच सकते हैं।
ExtractText कोड नोट्स में एक टिप्पणी:
सभी पाठ ड्राइंग कमांड का पता लगाएँ, इस क्रम में वे सामग्री स्ट्रीम में प्रदान किए गए हैं, और पाठ को निकालें। यह कुछ पीडीएफ फाइलों के लिए अच्छी तरह से काम करता है, लेकिन इस्तेमाल किए गए जनरेटर के आधार पर, दूसरों के लिए खराब है। भविष्य में इसे परिष्कृत किया जाएगा। इस फ़ंक्शन से आने वाले पाठ के आदेश पर भरोसा न करें, क्योंकि यह बदल जाएगा यदि यह फ़ंक्शन अधिक परिष्कृत है।
यह समस्या है या नहीं, यह इस बात पर निर्भर करता है कि आप पाठ के साथ क्या कर रहे हैं (उदाहरण के लिए यदि ऑर्डर में कोई फर्क नहीं पड़ता है, तो यह ठीक है, या यदि जनरेटर स्ट्रीम में पाठ जोड़ता है तो यह प्रदर्शित होगा, यह ठीक है) । मेरे पास दैनिक उपयोग में pyPdf निष्कर्षण कोड है, बिना किसी समस्या के।
आप लाइब्रेरी के रूप में भी पीडीऍफ़मिनर का उपयोग आसानी से कर सकते हैं। आपके पास पीडीएफ के सामग्री मॉडल तक पहुंच है, और अपना स्वयं का पाठ निष्कर्षण बना सकते हैं। मैंने नीचे दिए गए कोड का उपयोग करके पीडीएफ सामग्री को अर्ध-बृहदान्त्र से अलग पाठ में परिवर्तित करने के लिए ऐसा किया।
फ़ंक्शन केवल उनके y और x निर्देशांक के अनुसार TextItem सामग्री ऑब्जेक्ट्स को सॉर्ट करता है, और एक ही लाइन के रूप में एक ही लाइन के साथ वस्तुओं को अलग करता है, उसी के साथ वस्तुओं को अलग करता है ';' पात्र।
इस दृष्टिकोण का उपयोग करते हुए, मैं एक पीडीएफ से पाठ निकालने में सक्षम था कि कोई अन्य उपकरण आगे से पार्स करने के लिए उपयुक्त सामग्री को निकालने में सक्षम नहीं था। मैंने जिन अन्य उपकरणों की कोशिश की उनमें pdftotext, ps2ascii और ऑनलाइन टूल pdftextonline.com शामिल हैं।
pdfminer पीडीएफ-स्क्रैपिंग के लिए एक अमूल्य उपकरण है।
def pdf_to_csv(filename):
from pdflib.page import TextItem, TextConverter
from pdflib.pdfparser import PDFDocument, PDFParser
from pdflib.pdfinterp import PDFResourceManager, PDFPageInterpreter
class CsvConverter(TextConverter):
def __init__(self, *args, **kwargs):
TextConverter.__init__(self, *args, **kwargs)
def end_page(self, i):
from collections import defaultdict
lines = defaultdict(lambda : {})
for child in self.cur_item.objs:
if isinstance(child, TextItem):
(_,_,x,y) = child.bbox
line = lines[int(-y)]
line[x] = child.text
for y in sorted(lines.keys()):
line = lines[y]
self.outfp.write(";".join(line[x] for x in sorted(line.keys())))
self.outfp.write("\n")
# ... the following part of the code is a remix of the
# convert() function in the pdfminer/tools/pdf2text module
rsrc = PDFResourceManager()
outfp = StringIO()
device = CsvConverter(rsrc, outfp, "ascii")
doc = PDFDocument()
fp = open(filename, 'rb')
parser = PDFParser(doc, fp)
doc.initialize('')
interpreter = PDFPageInterpreter(rsrc, device)
for i, page in enumerate(doc.get_pages()):
outfp.write("START PAGE %d\n" % i)
interpreter.process_page(page)
outfp.write("END PAGE %d\n" % i)
device.close()
fp.close()
return outfp.getvalue()
अद्यतन :
उपरोक्त कोड एपीआई के एक पुराने संस्करण के खिलाफ लिखा गया है, नीचे मेरी टिप्पणी देखें।
pdfminer
, नहीं pdflib
)। मेरा सुझाव है कि आपके पास pdf2txt.py
PDFminer स्रोत के स्रोत पर एक नज़र है , ऊपर दिया गया कोड उस फ़ाइल के पुराने संस्करण से प्रेरित था।
slate
एक परियोजना है जो एक पुस्तकालय से PDFMiner का उपयोग करना बहुत आसान बनाता है:
>>> with open('example.pdf') as f:
... doc = slate.PDF(f)
...
>>> doc
[..., ..., ...]
>>> doc[1]
'Text from page 2...'
मुझे अजगर मॉड्यूल के भीतर एक विशिष्ट पीडीएफ को सादे पाठ में बदलने की आवश्यकता है। मैंने PDFMiner 20110515 का उपयोग किया , उनके PDF2txt.py टूल के माध्यम से पढ़ने के बाद मैंने यह सरल स्निपेट लिखा:
from cStringIO import StringIO
from pdfminer.pdfinterp import PDFResourceManager, process_pdf
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
def to_txt(pdf_path):
input_ = file(pdf_path, 'rb')
output = StringIO()
manager = PDFResourceManager()
converter = TextConverter(manager, output, laparams=LAParams())
process_pdf(manager, converter, input_)
return output.getvalue()
C:\Python27\Scripts\pdfminer\tools\pdf2txt.py
Pdf2txt.py कोड को पुन: व्यवस्थित करना जो pdfminer के साथ आता है; आप एक ऐसा कार्य कर सकते हैं जो पीडीएफ के लिए एक रास्ता लेगा; वैकल्पिक रूप से, एक आउटटाइप (txt | html | xml | टैग) और कमांडलाइन pdf2txt {'-o': '/path/to/outfile.txt' ...} की तरह खुलता है। डिफ़ॉल्ट रूप से, आप कॉल कर सकते हैं:
convert_pdf(path)
एक टेक्स्ट फ़ाइल बनाई जाएगी, जो मूल पीडीएफ के फाइल सिस्टम पर एक भाई-बहन है।
def convert_pdf(path, outtype='txt', opts={}):
import sys
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter, process_pdf
from pdfminer.converter import XMLConverter, HTMLConverter, TextConverter, TagExtractor
from pdfminer.layout import LAParams
from pdfminer.pdfparser import PDFDocument, PDFParser
from pdfminer.pdfdevice import PDFDevice
from pdfminer.cmapdb import CMapDB
outfile = path[:-3] + outtype
outdir = '/'.join(path.split('/')[:-1])
debug = 0
# input option
password = ''
pagenos = set()
maxpages = 0
# output option
codec = 'utf-8'
pageno = 1
scale = 1
showpageno = True
laparams = LAParams()
for (k, v) in opts:
if k == '-d': debug += 1
elif k == '-p': pagenos.update( int(x)-1 for x in v.split(',') )
elif k == '-m': maxpages = int(v)
elif k == '-P': password = v
elif k == '-o': outfile = v
elif k == '-n': laparams = None
elif k == '-A': laparams.all_texts = True
elif k == '-D': laparams.writing_mode = v
elif k == '-M': laparams.char_margin = float(v)
elif k == '-L': laparams.line_margin = float(v)
elif k == '-W': laparams.word_margin = float(v)
elif k == '-O': outdir = v
elif k == '-t': outtype = v
elif k == '-c': codec = v
elif k == '-s': scale = float(v)
#
CMapDB.debug = debug
PDFResourceManager.debug = debug
PDFDocument.debug = debug
PDFParser.debug = debug
PDFPageInterpreter.debug = debug
PDFDevice.debug = debug
#
rsrcmgr = PDFResourceManager()
if not outtype:
outtype = 'txt'
if outfile:
if outfile.endswith('.htm') or outfile.endswith('.html'):
outtype = 'html'
elif outfile.endswith('.xml'):
outtype = 'xml'
elif outfile.endswith('.tag'):
outtype = 'tag'
if outfile:
outfp = file(outfile, 'w')
else:
outfp = sys.stdout
if outtype == 'txt':
device = TextConverter(rsrcmgr, outfp, codec=codec, laparams=laparams)
elif outtype == 'xml':
device = XMLConverter(rsrcmgr, outfp, codec=codec, laparams=laparams, outdir=outdir)
elif outtype == 'html':
device = HTMLConverter(rsrcmgr, outfp, codec=codec, scale=scale, laparams=laparams, outdir=outdir)
elif outtype == 'tag':
device = TagExtractor(rsrcmgr, outfp, codec=codec)
else:
return usage()
fp = file(path, 'rb')
process_pdf(rsrcmgr, device, fp, pagenos, maxpages=maxpages, password=password)
fp.close()
device.close()
outfp.close()
return
PDFminer ने मुझे शायद एक लाइन दी [पेज 1 की 7 ...] एक पीडीएफ फाइल के हर पेज पर मैंने इसके साथ कोशिश की।
मेरे पास अब तक का सबसे अच्छा जवाब है pdftoipe, या यह C ++ कोड है जो Xpdf पर आधारित है।
pdftoipe का आउटपुट कैसा दिखता है, इसके लिए मेरा प्रश्न देखें ।
इसके अतिरिक्त PDFTextStream है जो एक व्यावसायिक जावा लाइब्रेरी है जिसका उपयोग पायथन से भी किया जा सकता है।
मैंने तर्क के pdftohtml
साथ उपयोग किया -xml
है, परिणाम को पढ़ें subprocess.Popen()
, इससे आपको पीडीएफ में पाठ के हर स्निपेट का x निर्देशांक, y समन्वय, चौड़ाई, ऊंचाई और फ़ॉन्ट मिलेगा । मुझे लगता है कि यह वही है जो 'उद्घोष' शायद इसलिए भी उपयोग करता है क्योंकि एक ही त्रुटि संदेश सामने आता है।
यदि आपको स्तंभ डेटा संसाधित करने की आवश्यकता है, तो यह थोड़ा अधिक जटिल हो जाता है क्योंकि आपको एक एल्गोरिथ्म का आविष्कार करना होगा जो आपकी पीडीएफ फाइल को सूट करता है। समस्या यह है कि पीडीएफ फाइलों को बनाने वाले कार्यक्रम वास्तव में पाठ को किसी तार्किक प्रारूप में रखना जरूरी नहीं समझते हैं। आप सरल सॉर्टिंग एल्गोरिदम की कोशिश कर सकते हैं और यह कभी-कभी काम करता है, लेकिन छोटे 'स्ट्रैगलर' और 'स्ट्रैस' हो सकते हैं, पाठ के टुकड़े जो उस क्रम में नहीं मिलते हैं जो आपने सोचा था कि वे करेंगे। इसलिए आपको क्रिएटिव होना पड़ेगा।
मुझे पीडीएफ के लिए काम करने में लगभग 5 घंटे लग गए। लेकिन यह अब बहुत अच्छा काम करता है। सौभाग्य।
आज वह समाधान मिला। मेरे लिए महान काम करता है। यहां तक कि पीएनजी छवियों के लिए पीडीएफ पृष्ठों का प्रतिपादन। http://www.swftools.org/gfx_tutorial.html