byte[] data; using (WebClient client = new WebClient()) { ICredentials cred; cred = new NetworkCredential("xmen@test.com", "mybestpassword"); client.Proxy = new WebProxy("192.168.0.1",8000); client.Credentials = cred; string myurl="http://mytestsite.com/source.jpg"; data = client.DownloadData(myUrl); } File.WriteAllBytes(@"c:\images\target.jpg", data);
Попробуйте PDFMiner. Это может извлечь текст из файлов PDF как HTML, SGML или "Теговый PDF" формат.
Теговый формат PDF, кажется, является самым чистым, и снятие XML-тэгов оставляет просто пустой текст.
А версия Python 3 доступна под:
pyPDF хорошо работает (предполагающий, что Вы работаете с правильно построенным PDFs). Если все, что Вы хотите, является текстом (с пробелами), можно просто сделать:
import pyPdf
pdf = pyPdf.PdfFileReader(open(filename, "rb"))
for page in pdf.pages:
print page.extractText()
можно также легко получить доступ к метаданным, данным изображения, и т.д.
А комментируют в примечаниях кода extractText:
Определяют местоположение всех текстовых команд рисования, в порядке, который им предоставляют в потоке содержания и извлекают текст. Это работает хорошо на некоторые файлы PDF, но плохо на других, в зависимости от используемого генератора. Это будет усовершенствовано в будущем. Не полагайтесь на порядок текста, выходящего из этой функции, когда это изменится, если эта функция будет сделана более сложной.
, Является ли это проблемой, зависит от того, что Вы делаете с текстом (например, если порядок не имеет значения, хорошо, или если генератор добавляет текст к потоку в порядке, это будет отображено, это прекрасно). У меня есть pyPdf код извлечения в обиходе без любых проблем.
PDFminer дал мне, возможно, одну строку [страница 1 7...] на каждой странице файла PDF, который я попробовал им.
лучший ответ, который я имею до сих пор, является pdftoipe или кодом C++, это основано на Xpdf.
видят мой вопрос для того, на что похож вывод pdftoipe.
Pdftotext программа с открытым исходным кодом (часть Xpdf), который Вы могли назвать из Python (не, что Вы попросили, но могли бы быть полезными). Я использовал его без проблем. Я думаю, что Google использует его в рабочем столе Google.
Можно также довольно легко использовать pdfminer в качестве библиотеки. Вы имеете доступ к модели содержания PDF и можете создать Ваше собственное извлечение текста. Я сделал это для преобразования содержания PDF в точку с запятой разделило текст, с помощью кода ниже.
функция просто сортирует объекты содержания TextItem согласно их y и координатам x и выходным объектам с той же координатой y как одна текстовая строка, разделяя объекты на той же строке с''; символы.
Используя этот подход, я смог извлечь текст из PDF, от которого никакой другой инструмент не смог извлечь содержание, подходящее для дальнейшего парсинга. Другие инструменты, которые я попробовал, включают pdftotext, ps2ascii и сетевой инструмент pdftextonline.com.
pdfminer является неоценимым инструментом для очистки PDF.
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()
ОБНОВЛЕНИЕ :
код выше записан против старой версии API, см. мой комментарий ниже.
Дополнительно существует PDFTextStream, который является коммерческой библиотекой Java, которой можно также пользоваться из Python.
Пакет PDFMiner был изменен с момента публикации codeape .
РЕДАКТИРОВАТЬ (снова):
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
и передал экземпляр LAParams конструктору CsvConverter.
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()
РЕДАКТИРОВАТЬ (еще раз):
Обновлено для версии 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()
Переделка кода pdf2txt.py, поставляемого с pdfminer; вы можете создать функцию, которая будет указывать путь к pdf; необязательно, outtype (txt | html | xml | tag) и выбирает как командную строку pdf2txt {'-o': '/path/to/outfile.txt' ...}. По умолчанию вы можете вызвать:
convert_pdf(path)
Будет создан текстовый файл, аналог в файловой системе исходного pdf.
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