pyPdf ignora las nuevas líneas en un archivo PDF

Estoy tratando de extraer cada página de un PDF como una cadena:

import pyPdf pages = [] pdf = pyPdf.PdfFileReader(file('g-reg-101.pdf', 'rb')) for i in range(0, pdf.getNumPages()): this_page = pdf.getPage(i).extractText() + "\n" this_page = " ".join(this_page.replace(u"\xa0", " ").strip().split()) pages.append(this_page.encode("ascii", "xmlcharrefreplace")) for page in pages: print '*' * 80 print page 

Pero esta secuencia de comandos ignora los caracteres de nueva línea, dejándome con cadenas desordenadas como information concerning an individual which, because of name, identifyingnumber, mark or description (es decir, debe leer el identifying number , no el identifying number identifyingumber ).

Aquí hay un ejemplo del tipo de PDF que estoy tratando de analizar.

No sé mucho acerca de la encoding PDF, pero creo que puede resolver su problema particular modificando pdf.py En el método PageObject.extractText , ves lo que está pasando:

 def extractText(self): [...] for operands,operator in content.operations: if operator == "Tj": _text = operands[0] if isinstance(_text, TextStringObject): text += _text elif operator == "T*": text += "\n" elif operator == "'": text += "\n" _text = operands[0] if isinstance(_text, TextStringObject): text += operands[0] elif operator == '"': _text = operands[2] if isinstance(_text, TextStringObject): text += "\n" text += _text elif operator == "TJ": for i in operands[0]: if isinstance(i, TextStringObject): text += i 

Si el operador es Tj o TJ (es Tj en su PDF de ejemplo), el texto simplemente se adjunta y no se agrega ninguna nueva línea. Ahora no necesariamente querría agregar una nueva línea, al menos si estoy leyendo la referencia de PDF correcta: Tj/TJ son simplemente los operadores de cadena de show únicos y múltiples, y la existencia de un separador de algún tipo no es obligatorio.

De todos modos, si modifica este código para que sea algo como

 def extractText(self, Tj_sep="", TJ_sep=""): 

[…]

  if operator == "Tj": _text = operands[0] if isinstance(_text, TextStringObject): text += Tj_sep text += _text 

[…]

  elif operator == "TJ": for i in operands[0]: if isinstance(i, TextStringObject): text += TJ_sep text += i 

entonces el comportamiento por defecto debería ser el mismo:

 In [1]: pdf.getPage(1).extractText()[1120:1250] Out[1]: u'ing an individual which, because of name, identifyingnumber, mark or description can be readily associated with a particular indiv' 

pero puedes cambiarlo cuando quieras:

 In [2]: pdf.getPage(1).extractText(Tj_sep=" ")[1120:1250] Out[2]: u'ta" means any information concerning an individual which, because of name, identifying number, mark or description can be readily ' 

o

 In [3]: pdf.getPage(1).extractText(Tj_sep="\n")[1120:1250] Out[3]: u'ta" means any information concerning an individual which, because of name, identifying\nnumber, mark or description can be readily ' 

Alternativamente, puede simplemente agregar los separadores usted mismo modificando los operandos en el lugar, pero eso podría romper otra cosa (los métodos como get_original_bytes me ponen nervioso).

Finalmente, no tiene que editar pdf.py sí mismo si no lo desea: simplemente puede extraer este método en una función.

pyPdf no está realmente hecho para este tipo de extracción de texto, intente pdfminer (o use pdftotext o algo así, si no le importa crear otro proceso)