<p>Is there any python module to convert PDF files into text? I tried <a href="http://code.activestate.com/recipes/511465/" rel="noreferrer">one piece of code</a> found in Activestate which uses pypdf but the text generated had no space between and was of no use. </p>

[{'answer_id': 25689, 'author': 'David Crow', 'author_id': 2783, 'author_profile': 'https://Stackoverflow.com/users/2783', 'pm_score': 8, 'selected': True, 'text': '<p>Try <a href="http://www.unixuser.org/~euske/python/pdfminer/index.html" rel="noreferrer">PDFMiner</a>. It can extract text from PDF files as HTML, SGML or "Tagged PDF" format.</p>\n\n<p>The Tagged PDF format seems to be the cleanest, and stripping out the XML tags leaves just the bare text.</p>\n\n<p>A Python 3 version is available under:</p>\n\n<ul>\n<li><a href="https://github.com/pdfminer/pdfminer.six" rel="noreferrer">https://github.com/pdfminer/pdfminer.six</a></li>\n</ul>\n'}, {'answer_id': 27252, 'author': 'sphereinabox', 'author_id': 2775, 'author_profile': 'https://Stackoverflow.com/users/2775', 'pm_score': 1, 'selected': False, 'text': '<p>PDFminer gave me perhaps one line [page 1 of 7...] on every page of a pdf file I tried with it.</p>\n\n<p>The best answer I have so far is pdftoipe, or the c++ code it\'s based on Xpdf.</p>\n\n<p>see <a href="https://stackoverflow.com/questions/25550/whats-the-best-way-to-importread-data-from-pdf-files">my question</a> for what the output of pdftoipe looks like.</p>\n'}, {'answer_id': 31923, 'author': 'Jamie', 'author_id': 3363, 'author_profile': 'https://Stackoverflow.com/users/3363', 'pm_score': 6, 'selected': False, 'text': '<p><a href="http://en.wikipedia.org/wiki/Pdftotext" rel="noreferrer">Pdftotext</a> An open source program (part of Xpdf) which you could call from python (not what you asked for but might be useful). I\'ve used it with no problems. I think google use it in google desktop.</p>\n'}, {'answer_id': 48154, 'author': 'Tony Meyer', 'author_id': 4966, 'author_profile': 'https://Stackoverflow.com/users/4966', 'pm_score': 6, 'selected': False, 'text': '<p><a href="http://pybrary.net/pyPdf/" rel="noreferrer">pyPDF</a> works fine (assuming that you\'re working with well-formed PDFs).  If all you want is the text (with spaces), you can just do:</p>\n\n<pre><code>import pyPdf\npdf = pyPdf.PdfFileReader(open(filename, "rb"))\nfor page in pdf.pages:\n    print page.extractText()\n</code></pre>\n\n<p>You can also easily get access to the metadata, image data, and so forth.</p>\n\n<p>A comment in the extractText code notes:</p>\n\n<blockquote>\n  <p>Locate all text drawing commands, in\n  the order they are provided in the\n  content stream, and extract the text. \n  This works well for some PDF files,\n  but poorly for others, depending on\n  the generator used.  This will be\n  refined in the future.  Do not rely on\n  the order of text coming out of this\n  function, as it will change if this\n  function is made more sophisticated.</p>\n</blockquote>\n\n<p>Whether or not this is a problem depends on what you\'re doing with the text (e.g. if the order doesn\'t matter, it\'s fine, or if the generator adds text to the stream in the order it will be displayed, it\'s fine).  I have pyPdf extraction code in daily use, without any problems.</p>\n'}, {'answer_id': 284641, 'author': 'msanders', 'author_id': 1002, 'author_profile': 'https://Stackoverflow.com/users/1002', 'pm_score': 1, 'selected': False, 'text': '<p>Additionally there is <a href="http://snowtide.com/PDFTextStream" rel="nofollow noreferrer">PDFTextStream</a> which is a commercial Java library that can also be used from Python.</p>\n'}, {'answer_id': 314249, 'author': 'codeape', 'author_id': 3571, 'author_profile': 'https://Stackoverflow.com/users/3571', 'pm_score': 4, 'selected': False, 'text': '<p>You can also quite easily use pdfminer as a library. You have access to the pdf\'s content model, and can create your own text extraction. I did this to convert pdf contents to semi-colon separated text, using the code below.</p>\n\n<p>The function simply sorts the TextItem content objects according to their y and x coordinates, and outputs items with the same y coordinate as one text line, separating the objects on the same line with \';\' characters.</p>\n\n<p>Using this approach, I was able to extract text from a pdf that no other tool was able to extract content suitable for further parsing from. Other tools I tried include pdftotext, ps2ascii and the online tool pdftextonline.com.</p>\n\n<p>pdfminer is an invaluable tool for pdf-scraping.</p>\n\n<pre><code>\ndef pdf_to_csv(filename):\n    from pdflib.page import TextItem, TextConverter\n    from pdflib.pdfparser import PDFDocument, PDFParser\n    from pdflib.pdfinterp import PDFResourceManager, PDFPageInterpreter\n\n    class CsvConverter(TextConverter):\n        def __init__(self, *args, **kwargs):\n            TextConverter.__init__(self, *args, **kwargs)\n\n        def end_page(self, i):\n            from collections import defaultdict\n            lines = defaultdict(lambda : {})\n            for child in self.cur_item.objs:\n                if isinstance(child, TextItem):\n                    (_,_,x,y) = child.bbox\n                    line = lines[int(-y)]\n                    line[x] = child.text\n\n            for y in sorted(lines.keys()):\n                line = lines[y]\n                self.outfp.write(";".join(line[x] for x in sorted(line.keys())))\n                self.outfp.write("\\n")\n\n    # ... the following part of the code is a remix of the \n    # convert() function in the pdfminer/tools/pdf2text module\n    rsrc = PDFResourceManager()\n    outfp = StringIO()\n    device = CsvConverter(rsrc, outfp, "ascii")\n\n    doc = PDFDocument()\n    fp = open(filename, \'rb\')\n    parser = PDFParser(doc, fp)\n    doc.initialize(\'\')\n\n    interpreter = PDFPageInterpreter(rsrc, device)\n\n    for i, page in enumerate(doc.get_pages()):\n        outfp.write("START PAGE %d\\n" % i)\n        interpreter.process_page(page)\n        outfp.write("END PAGE %d\\n" % i)\n\n    device.close()\n    fp.close()\n\n    return outfp.getvalue()\n\n</code></pre>\n\n<p><strong>UPDATE</strong>:</p>\n\n<p>The code above is written against an old version of the API, see my comment below.</p>\n'}, {'answer_id': 1257121, 'author': 'tgray', 'author_id': 64206, 'author_profile': 'https://Stackoverflow.com/users/64206', 'pm_score': 7, 'selected': False, 'text': '<p>The <a href="http://www.unixuser.org/~euske/python/pdfminer/index.html" rel="noreferrer">PDFMiner</a> package has changed since <a href="https://stackoverflow.com/users/3571/codeape">codeape</a> posted.  </p>\n\n<p><strong>EDIT (again):</strong></p>\n\n<p>PDFMiner has been updated again in version <code>20100213</code></p>\n\n<p>You can check the version you have installed with the following:</p>\n\n<pre><code>&gt;&gt;&gt; import pdfminer\n&gt;&gt;&gt; pdfminer.__version__\n\'20100213\'\n</code></pre>\n\n<p>Here\'s the updated version (with comments on what I changed/added):</p>\n\n<pre><code>def pdf_to_csv(filename):\n    from cStringIO import StringIO  #&lt;-- added so you can copy/paste this to try it\n    from pdfminer.converter import LTTextItem, TextConverter\n    from pdfminer.pdfparser import PDFDocument, PDFParser\n    from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter\n\n    class CsvConverter(TextConverter):\n        def __init__(self, *args, **kwargs):\n            TextConverter.__init__(self, *args, **kwargs)\n\n        def end_page(self, i):\n            from collections import defaultdict\n            lines = defaultdict(lambda : {})\n            for child in self.cur_item.objs:\n                if isinstance(child, LTTextItem):\n                    (_,_,x,y) = child.bbox                   #&lt;-- changed\n                    line = lines[int(-y)]\n                    line[x] = child.text.encode(self.codec)  #&lt;-- changed\n\n            for y in sorted(lines.keys()):\n                line = lines[y]\n                self.outfp.write(";".join(line[x] for x in sorted(line.keys())))\n                self.outfp.write("\\n")\n\n    # ... the following part of the code is a remix of the \n    # convert() function in the pdfminer/tools/pdf2text module\n    rsrc = PDFResourceManager()\n    outfp = StringIO()\n    device = CsvConverter(rsrc, outfp, codec="utf-8")  #&lt;-- changed \n        # becuase my test documents are utf-8 (note: utf-8 is the default codec)\n\n    doc = PDFDocument()\n    fp = open(filename, \'rb\')\n    parser = PDFParser(fp)       #&lt;-- changed\n    parser.set_document(doc)     #&lt;-- added\n    doc.set_parser(parser)       #&lt;-- added\n    doc.initialize(\'\')\n\n    interpreter = PDFPageInterpreter(rsrc, device)\n\n    for i, page in enumerate(doc.get_pages()):\n        outfp.write("START PAGE %d\\n" % i)\n        interpreter.process_page(page)\n        outfp.write("END PAGE %d\\n" % i)\n\n    device.close()\n    fp.close()\n\n    return outfp.getvalue()\n</code></pre>\n\n<p><strong>Edit (yet again):</strong></p>\n\n<p>Here is an update for the latest version in <a href="http://pypi.python.org/pypi/pdfminer/" rel="noreferrer">pypi</a>, <code>20100619p1</code>.  In short I replaced <code>LTTextItem</code> with <code>LTChar</code> and passed an instance of LAParams to the CsvConverter constructor.</p>\n\n<pre><code>def pdf_to_csv(filename):\n    from cStringIO import StringIO  \n    from pdfminer.converter import LTChar, TextConverter    #&lt;-- changed\n    from pdfminer.layout import LAParams\n    from pdfminer.pdfparser import PDFDocument, PDFParser\n    from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter\n\n    class CsvConverter(TextConverter):\n        def __init__(self, *args, **kwargs):\n            TextConverter.__init__(self, *args, **kwargs)\n\n        def end_page(self, i):\n            from collections import defaultdict\n            lines = defaultdict(lambda : {})\n            for child in self.cur_item.objs:\n                if isinstance(child, LTChar):               #&lt;-- changed\n                    (_,_,x,y) = child.bbox                   \n                    line = lines[int(-y)]\n                    line[x] = child.text.encode(self.codec)\n\n            for y in sorted(lines.keys()):\n                line = lines[y]\n                self.outfp.write(";".join(line[x] for x in sorted(line.keys())))\n                self.outfp.write("\\n")\n\n    # ... the following part of the code is a remix of the \n    # convert() function in the pdfminer/tools/pdf2text module\n    rsrc = PDFResourceManager()\n    outfp = StringIO()\n    device = CsvConverter(rsrc, outfp, codec="utf-8", laparams=LAParams())  #&lt;-- changed\n        # becuase my test documents are utf-8 (note: utf-8 is the default codec)\n\n    doc = PDFDocument()\n    fp = open(filename, \'rb\')\n    parser = PDFParser(fp)       \n    parser.set_document(doc)     \n    doc.set_parser(parser)       \n    doc.initialize(\'\')\n\n    interpreter = PDFPageInterpreter(rsrc, device)\n\n    for i, page in enumerate(doc.get_pages()):\n        outfp.write("START PAGE %d\\n" % i)\n        if page is not None:\n            interpreter.process_page(page)\n        outfp.write("END PAGE %d\\n" % i)\n\n    device.close()\n    fp.close()\n\n    return outfp.getvalue()\n</code></pre>\n\n<p><strong>EDIT (one more time):</strong></p>\n\n<p>Updated for version <code>20110515</code> (thanks to Oeufcoque Penteano!):</p>\n\n<pre><code>def pdf_to_csv(filename):\n    from cStringIO import StringIO  \n    from pdfminer.converter import LTChar, TextConverter\n    from pdfminer.layout import LAParams\n    from pdfminer.pdfparser import PDFDocument, PDFParser\n    from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter\n\n    class CsvConverter(TextConverter):\n        def __init__(self, *args, **kwargs):\n            TextConverter.__init__(self, *args, **kwargs)\n\n        def end_page(self, i):\n            from collections import defaultdict\n            lines = defaultdict(lambda : {})\n            for child in self.cur_item._objs:                #&lt;-- changed\n                if isinstance(child, LTChar):\n                    (_,_,x,y) = child.bbox                   \n                    line = lines[int(-y)]\n                    line[x] = child._text.encode(self.codec) #&lt;-- changed\n\n            for y in sorted(lines.keys()):\n                line = lines[y]\n                self.outfp.write(";".join(line[x] for x in sorted(line.keys())))\n                self.outfp.write("\\n")\n\n    # ... the following part of the code is a remix of the \n    # convert() function in the pdfminer/tools/pdf2text module\n    rsrc = PDFResourceManager()\n    outfp = StringIO()\n    device = CsvConverter(rsrc, outfp, codec="utf-8", laparams=LAParams())\n        # becuase my test documents are utf-8 (note: utf-8 is the default codec)\n\n    doc = PDFDocument()\n    fp = open(filename, \'rb\')\n    parser = PDFParser(fp)       \n    parser.set_document(doc)     \n    doc.set_parser(parser)       \n    doc.initialize(\'\')\n\n    interpreter = PDFPageInterpreter(rsrc, device)\n\n    for i, page in enumerate(doc.get_pages()):\n        outfp.write("START PAGE %d\\n" % i)\n        if page is not None:\n            interpreter.process_page(page)\n        outfp.write("END PAGE %d\\n" % i)\n\n    device.close()\n    fp.close()\n\n    return outfp.getvalue()\n</code></pre>\n'}, {'answer_id': 3276880, 'author': 'Skylar Saveland', 'author_id': 177293, 'author_profile': 'https://Stackoverflow.com/users/177293', 'pm_score': 3, 'selected': False, 'text': "<p>Repurposing the pdf2txt.py code that comes with pdfminer; you can make a function that will take a path to the pdf; optionally, an outtype (txt|html|xml|tag) and opts like the commandline pdf2txt {'-o': '/path/to/outfile.txt' ...}.  By default, you can call:</p>\n\n<pre><code>convert_pdf(path)\n</code></pre>\n\n<p>A text file will be created, a sibling on the filesystem to the original pdf.</p>\n\n<pre><code>def convert_pdf(path, outtype='txt', opts={}):\n    import sys\n    from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter, process_pdf\n    from pdfminer.converter import XMLConverter, HTMLConverter, TextConverter, TagExtractor\n    from pdfminer.layout import LAParams\n    from pdfminer.pdfparser import PDFDocument, PDFParser\n    from pdfminer.pdfdevice import PDFDevice\n    from pdfminer.cmapdb import CMapDB\n\n    outfile = path[:-3] + outtype\n    outdir = '/'.join(path.split('/')[:-1])\n\n    debug = 0\n    # input option\n    password = ''\n    pagenos = set()\n    maxpages = 0\n    # output option\n    codec = 'utf-8'\n    pageno = 1\n    scale = 1\n    showpageno = True\n    laparams = LAParams()\n    for (k, v) in opts:\n        if k == '-d': debug += 1\n        elif k == '-p': pagenos.update( int(x)-1 for x in v.split(',') )\n        elif k == '-m': maxpages = int(v)\n        elif k == '-P': password = v\n        elif k == '-o': outfile = v\n        elif k == '-n': laparams = None\n        elif k == '-A': laparams.all_texts = True\n        elif k == '-D': laparams.writing_mode = v\n        elif k == '-M': laparams.char_margin = float(v)\n        elif k == '-L': laparams.line_margin = float(v)\n        elif k == '-W': laparams.word_margin = float(v)\n        elif k == '-O': outdir = v\n        elif k == '-t': outtype = v\n        elif k == '-c': codec = v\n        elif k == '-s': scale = float(v)\n    #\n    CMapDB.debug = debug\n    PDFResourceManager.debug = debug\n    PDFDocument.debug = debug\n    PDFParser.debug = debug\n    PDFPageInterpreter.debug = debug\n    PDFDevice.debug = debug\n    #\n    rsrcmgr = PDFResourceManager()\n    if not outtype:\n        outtype = 'txt'\n        if outfile:\n            if outfile.endswith('.htm') or outfile.endswith('.html'):\n                outtype = 'html'\n            elif outfile.endswith('.xml'):\n                outtype = 'xml'\n            elif outfile.endswith('.tag'):\n                outtype = 'tag'\n    if outfile:\n        outfp = file(outfile, 'w')\n    else:\n        outfp = sys.stdout\n    if outtype == 'txt':\n        device = TextConverter(rsrcmgr, outfp, codec=codec, laparams=laparams)\n    elif outtype == 'xml':\n        device = XMLConverter(rsrcmgr, outfp, codec=codec, laparams=laparams, outdir=outdir)\n    elif outtype == 'html':\n        device = HTMLConverter(rsrcmgr, outfp, codec=codec, scale=scale, laparams=laparams, outdir=outdir)\n    elif outtype == 'tag':\n        device = TagExtractor(rsrcmgr, outfp, codec=codec)\n    else:\n        return usage()\n\n    fp = file(path, 'rb')\n    process_pdf(rsrcmgr, device, fp, pagenos, maxpages=maxpages, password=password)\n    fp.close()\n    device.close()\n\n    outfp.close()\n    return\n</code></pre>\n"}, {'answer_id': 4169679, 'author': 'Decora', 'author_id': 506335, 'author_profile': 'https://Stackoverflow.com/users/506335', 'pm_score': 1, 'selected': False, 'text': "<p>I have used <code>pdftohtml</code> with the <code>-xml</code> argument, read the result with <code>subprocess.Popen()</code>, that will give you x coord, y coord, width, height, and font, of every <em>snippet</em> of text in the pdf. I think this is what 'evince' probably uses too because the same error messages spew out. </p>\n\n<p>If you need to process columnar data, it gets slightly more complicated as you have to invent an algorithm that suits your pdf file. The problem is that the programs that make PDF files don't really necessarily lay out the text in any logical format. You can try simple sorting algorithms and it works sometimes, but there can be little 'stragglers' and 'strays', pieces of text that don't get put in the order you thought they would. So you have to get creative. </p>\n\n<p>It took me about 5 hours to figure out one for the pdf's I was working on. But it works pretty good now. Good luck. </p>\n"}, {'answer_id': 4846592, 'author': 'Andrey Shipilov', 'author_id': 375649, 'author_profile': 'https://Stackoverflow.com/users/375649', 'pm_score': 0, 'selected': False, 'text': '<p>Found that solution today. Works great for me. Even rendering PDF pages to PNG images.\n<a href="http://www.swftools.org/gfx_tutorial.html" rel="nofollow">http://www.swftools.org/gfx_tutorial.html</a></p>\n'}, {'answer_id': 4846622, 'author': 'Tim McNamara', 'author_id': 395287, 'author_profile': 'https://Stackoverflow.com/users/395287', 'pm_score': 4, 'selected': False, 'text': '<p><a href="http://pypi.python.org/pypi/slate"><code>slate</code></a> is a project that makes it very simple to use PDFMiner from a library:</p>\n\n<pre><code>&gt;&gt;&gt; with open(\'example.pdf\') as f:\n...    doc = slate.PDF(f)\n...\n&gt;&gt;&gt; doc\n[..., ..., ...]\n&gt;&gt;&gt; doc[1]\n\'Text from page 2...\'   \n</code></pre>\n'}, {'answer_id': 16796554, 'author': 'gonz', 'author_id': 323751, 'author_profile': 'https://Stackoverflow.com/users/323751', 'pm_score': 3, 'selected': False, 'text': '<p>I needed to convert a specific PDF to plain text within a python module. I used <a href="http://www.unixuser.org/~euske/python/pdfminer/index.html" rel="noreferrer">PDFMiner</a> 20110515, after reading through their <a href="https://github.com/euske/pdfminer/blob/master/tools/pdf2txt.py" rel="noreferrer">pdf2txt.py</a> tool I wrote this simple snippet:</p>\n\n<pre><code>from cStringIO import StringIO\nfrom pdfminer.pdfinterp import PDFResourceManager, process_pdf\nfrom pdfminer.converter import TextConverter\nfrom pdfminer.layout import LAParams\n\ndef to_txt(pdf_path):\n    input_ = file(pdf_path, \'rb\')\n    output = StringIO()\n\n    manager = PDFResourceManager()\n    converter = TextConverter(manager, output, laparams=LAParams())\n    process_pdf(manager, converter, input_)\n\n    return output.getvalue() \n</code></pre>\n'}, {'answer_id': 21564675, 'author': 'user3272884', 'author_id': 3272884, 'author_profile': 'https://Stackoverflow.com/users/3272884', 'pm_score': 6, 'selected': False, 'text': "<p>Since none for these solutions support the latest version of PDFMiner I wrote a simple solution that will return text of a pdf using PDFMiner. This will work for those who are getting import errors with <code>process_pdf</code> </p>\n\n<pre><code>import sys\nfrom pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter\nfrom pdfminer.pdfpage import PDFPage\nfrom pdfminer.converter import XMLConverter, HTMLConverter, TextConverter\nfrom pdfminer.layout import LAParams\nfrom cStringIO import StringIO\n\ndef pdfparser(data):\n\n    fp = file(data, 'rb')\n    rsrcmgr = PDFResourceManager()\n    retstr = StringIO()\n    codec = 'utf-8'\n    laparams = LAParams()\n    device = TextConverter(rsrcmgr, retstr, codec=codec, laparams=laparams)\n    # Create a PDF interpreter object.\n    interpreter = PDFPageInterpreter(rsrcmgr, device)\n    # Process each page contained in the document.\n\n    for page in PDFPage.get_pages(fp):\n        interpreter.process_page(page)\n        data =  retstr.getvalue()\n\n    print data\n\nif __name__ == '__main__':\n    pdfparser(sys.argv[1])  \n</code></pre>\n\n<p>See below code that works for Python 3:</p>\n\n<pre><code>import sys\nfrom pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter\nfrom pdfminer.pdfpage import PDFPage\nfrom pdfminer.converter import XMLConverter, HTMLConverter, TextConverter\nfrom pdfminer.layout import LAParams\nimport io\n\ndef pdfparser(data):\n\n    fp = open(data, 'rb')\n    rsrcmgr = PDFResourceManager()\n    retstr = io.StringIO()\n    codec = 'utf-8'\n    laparams = LAParams()\n    device = TextConverter(rsrcmgr, retstr, codec=codec, laparams=laparams)\n    # Create a PDF interpreter object.\n    interpreter = PDFPageInterpreter(rsrcmgr, device)\n    # Process each page contained in the document.\n\n    for page in PDFPage.get_pages(fp):\n        interpreter.process_page(page)\n        data =  retstr.getvalue()\n\n    print(data)\n\nif __name__ == '__main__':\n    pdfparser(sys.argv[1])  \n</code></pre>\n"}]
['https://Stackoverflow.com/questions/25665', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/1448/']