将PDF表单数据转换为CSV格式

3

我正在尝试将多个可填写pdf表单中输入的数据转换为一个CSV文件。
这段代码包含以下几个步骤:

  1. 打开新的.CSV文件(标题行)
  2. 使用“ for...in”循环打开多个pdf表单
  3. 将填写在表单字段中的数据转换为CSV

但是,在运行命令时我收到了错误信息:

fc-int01-generateAppearances: None
Traceback (most recent call last):
    File "C:\Python27\Scripts\test3.py", line 31, in <module>
        writer.writerow(value)
    _csv.Error: sequence expected

如果我只是在Python中打印值(表单数据),那么它可以工作。但导入数据不行。可能还存在从行到列转换值的问题。希望我说得清楚。

这是我的代码:

import glob
import os
import sys
import csv
from pdfminer.pdfparser import PDFParser
from pdfminer.pdfdocument import PDFDocument
from pdfminer.pdftypes import resolve1

#input file path for specific file
#filename = "C:\Python27\Scripts\MH_1.pdf"
#fp = open(filename, 'rb')

#open new csv file
out_file=open('C:\Users\Wonen\Downloads\Test\output.csv', 'w+')
writer = csv.writer(out_file)
#header row
writer.writerow(('Name coordinator', 'Date', 'Address', 'District',
                 'City', 'Complaintnr'))

#enter folder path to open multiple files
path = 'C:\Users\Wonen\Downloads\Test'
for filename in glob.glob(os.path.join(path, '*.pdf')):
    fp = open(filename, 'rb')
    #read pdf's
    parser = PDFParser(fp)
    doc = PDFDocument(parser)
    #doc.initialize()    # <<if password is required
    fields = resolve1(doc.catalog['AcroForm'])['Fields']
    for i in fields:
        field = resolve1(i)
        name, value = field.get('T'), field.get('V')
        print '{0}: {1}'.format(name, value)
        writer.writerow(value)

使用print(repr(value))输出文本pdf(包括所有输出)的结果:

None
'Crip Gang'
None
None
None
/Ja
None
/1
/1
None
None
/Ja
/Ja
None
None
None
'wfwf'
'sd'
'dfwf'
'ffasf'
'tsdbd'
'dfadfasdf'
None
'df'
None
'asdff'
None
'wff'
None
'ffs'
None
None
None
None
None
None
None
None
None
None
None
'1'
'2'
'7'
/0
'Ja'
'Two unlimited'
'Captain Jack'
None
'www.kijkbijmij.nl'
'Onderverhuur'
/Ja

等等。 "None" 代表“空文本框”; 而“1”和“0”则代表“是”和“否”的输出。


1
在错误发生前一行,print函数的输出是什么? - adrianus
"value" 需要是一个序列。如果不是,请尝试 writer.writerow([value]) - martineau
@martineau,问题几乎解决了。我希望它是一行逗号分隔的值(清除中间的空格)。但这远远超出了我对Python的了解。 - Readazoid
writerow()会在传递给它作为参数的序列中的每个元素之间放置一个逗号。当您使用[value]时,该序列仅包含一个元素,即value中的所有内容。请展示一下value中的数据长什么样子。如果每个字段的数据都不同,那么我们也需要知道这一点。 - martineau
1
@martineau 我编辑了这条评论。 - Readazoid
1个回答

0

尝试按照以下方式更改代码的最后一部分:

    .
    .
    .
#enter folder path to open multiple files
path = 'C:\Users\Wonen\Downloads\Test'
for filename in glob.glob(os.path.join(path, '*.pdf')):
    fp = open(filename, 'rb')
    #read pdf's
    parser = PDFParser(fp)
    doc = PDFDocument(parser)
    #doc.initialize()    # <<if password is required
    fields = resolve1(doc.catalog['AcroForm'])['Fields']
    row = []
    for i in fields:
        field = resolve1(i)
        name, value = field.get('T'), field.get('V')
        row.append(value)
    writer.writerow(row)

out_file.close()

不清楚这是否有效,但它可能为您提供解决问题所需的信息。

一个令人困惑的地方是对于 CSV 的第一行标题:

writer.writerow(('Name coordinator', 'Date', 'Address','District','City', 'Complaintnr'))

该代码定义了每行写入的字段值数量。这意味着fields应该是一个按照顺序包含这6个项目数据的列表。

您需要弄清楚如何将每个fields组中的内容转换为包含6个数据项的row列表。这就是我答案中的代码所做的事情——我认为是这样,但无法测试。


这看起来好多了!我还有两个问题。1.一些值字段允许“回车”,并使输出在csv中跳行。2.脚本向后抓取表单。 - Readazoid
writer.writerow(('Name coordinator', 'Date', 'Address','District','City', 'Complaintnr')) 将我的 CSV 文件中的标题行写入。我给出了一个示例标题代码。该表单有 25 个问题,因此将包含 25 个标题,而不是 6 个。这一行比这里显示的要长得多。 - Readazoid
writer.writerow(list(reversed(row))) 正是我所需要的,再次感谢。"在将值附加到行列表之前检查它们的值"我不知道该怎么做。虽然这是个好建议,但除非你已经有一个解决方案了,否则我会在网上搜索的 :-) - Readazoid
1
您可以在 row.append() 之前使用一系列的 if 语句来检查和纠正值,例如:if value is None: value = ''elif value == '1': value = 'yes' 等等。如果我的回答对您有帮助,请考虑接受和/或点赞。谢谢。 - martineau
如果值等于None: 打印 'ok' elif '\n' in value:
value.replace('\n',' ')我正在尝试删除换行符,但是我收到错误“TypeError:类型为'PSLiteral'的参数不可迭代”>>> for line value.replace('\ n',' ')
- Readazoid
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接