У меня есть файл PDF, мне нужно преобразовать его в файл CSV, это мой пример файла PDF в качестве ссылки https://online.flippingbook.com/view/352975479/ используемый код
import re
import parse
import pdfplumber
import pandas as pd
from collections import namedtuple
file = "Battery Voltage.pdf"
lines = []
total_check = 0
with pdfplumber.open(file) as pdf:
pages = pdf.pages
for page in pdf.pages:
text = page.extract_text()
for line in text.split('\n'):
print(line)
с приведенным выше сценарием я не получаю надлежащего вывода, столбец «Время» «AM» появляется в следующей строке. Вывод, который я получаю, такой
В этом конкретном случае выходные данные имеют шаблон, поэтому вы можете исправить это, найдя строки с содержимым «AM» или «PM» и добавив их в конец третьего поля предыдущей строки после разделения на пробел.
Для таких случаев создайте анализатор, который преобразует непригодные данные во что-то, что вы можете использовать.
Приведенная ниже логика преобразует именно этот файл в CSV, но будет работать только с этим конкретным содержимым файла.
Обратите внимание, что для этого конкретного файла вы можете игнорировать AM/PM, поскольку время указано в 24-часовом формате.
import pdfplumber
file = "Battery Voltage.pdf"
skiplines = [
"Battery Voltage",
"AM",
"PM",
"Sr No DateTIme Voltage (v) Ignition",
""
]
with open("output.csv", "w") as outfile:
header = "serialnumber;date;time;voltage;ignition\n"
outfile.write(header)
with pdfplumber.open(file) as pdf:
for page in pdf.pages:
for line in page.extract_text().split('\n'):
if line.strip() in skiplines:
continue
outfile.write(";".join(line.split())+"\n")
РЕДАКТИРОВАТЬ
Итак, файлы JSON в python — это просто список элементов dict (да, это упрощение).
Единственное, что вам нужно изменить, это то, как вы на самом деле обрабатываете линии. Суть логики не меняется...
import pdfplumber
import json
file = "Battery Voltage.pdf"
skiplines = [
"Battery Voltage",
"AM",
"PM",
"Sr No DateTIme Voltage (v) Ignition",
""
]
result = []
with pdfplumber.open(file) as pdf:
for page in pdf.pages:
for line in page.extract_text().split("\n"):
if line.strip() in skiplines:
continue
serialnumber, date, time, voltage, ignition = line.split()
result.append(
{
"serialnumber": serialnumber,
"date": date,
"time": time,
"voltage": voltage,
"ignition": ignition,
}
)
with open("output.json", "w") as outfile:
json.dump(result, outfile)
Это может помочь вам увидеть, как поверхность PDF-файла отображается на экране. так что одна строка обычного текста размещается на дисплее по частям. (Здесь я подчеркиваю, где должен быть размещен первый AM.
В качестве побочного вопроса я думаю, что первый AM в файле на первый взгляд закодирован как этот блок.
BT
/F1 12 Tf
1 0 0 1 224.20265 754.6322 Tm
[<001D001E>] TJ
ET
Где в этой области 1D = A и 1E = M
Итак, если вы хотите извлечь каждую СТРОКУ в том виде, в каком она отображается, самый простой способ — использовать библиотеку, такую как pdftotext, которая специально выводит каждую строку текста так, как она отображается на странице.
Таким образом, используя такую атаку, как табличное разделение запятыми, вы можете ожидать, что каждому AM
будет предоставлена своя строка. Что по логике должно быть " ",AM," "," "
, но некоторые экстракторы должны говорить nan, AM, nan, nan
Как текст это выглядит так из одной программируемой строки
pdftotext -layout "Battery Voltage.pdf"
Это выведет «Battery Voltage.txt» в той же рабочей папке.
Затем размещение этого в электронной таблице становится
Теперь мы можем экспортировать в пару кликов (больше не будет) как «правильный вывод» csv вместе со всеми его странностями, которые влечет за собой csv.
,,Battery Vo,ltage,
Sr No,DateT,Ime,Voltage (v),Ignition
1,01/11/2022,00:08:10,47.15,Off
,AM,,,
2,01/11/2022,00:23:10,47.15,Off
,AM,,,
3,01/11/2022,00:38:10,47.15,Off
,AM,,,
4,01/11/2022,00:58:10,47.15,Off
,AM,,,
5,01/11/2022,01:18:10,47.15,Off
,AM,,,
6,01/11/2022,01:33:10,47.15,Off
,AM,,,
7,01/11/2022,01:48:10,47.15,Off
,AM,,,
8,01/11/2022,02:03:10,47.15,Off
,AM,,,
9,01/11/2022,02:18:10,47.15,Off
,AM,,,
10,01/11/2022,02:37:12,47.15,Off
,AM,,,
Итак, если правки не были внесены до создания csv, проще опубликовать процесс в редакторе, например, на этой html-странице (нет необходимости в дополнительных приложениях).
,,Battery,Voltage,
Sr No,Date,Time,Voltage (v),Ignition
1,01/11/2022,00:08:10,47.15,Off,AM,,,
2,01/11/2022,00:23:10,47.15,Off,AM,,,
3,01/11/2022,00:38:10,47.15,Off,AM,,,
4,01/11/2022,00:58:10,47.15,Off,AM,,,
5,01/11/2022,01:18:10,47.15,Off,AM,,,
6,01/11/2022,01:33:10,47.15,Off,AM,,,
7,01/11/2022,01:48:10,47.15,Off,AM,,,
8,01/11/2022,02:03:10,47.15,Off,AM,,,
9,01/11/2022,02:18:10,47.15,Off,AM,,,
10,01/11/2022,02:37:12,47.15,Off,AM,,,
Затем при повторном импорте он выглядит более человеческим
В обсуждениях было подтверждено, что все, что нужно, это средство для структурированного списка и первого анализа с использованиемpdftotext -layout -nopgbrk -x 0 -y 60 -W 800 -H 800 -fixed 6 "Battery Voltage.pdf" &type "battery voltage.txt"|findstr "O">battery.txt
будет выводить регулируемые столбцы данных для кадрирования с фиксированным заголовком или разделением или иным образом с использованием очищенных данных.
1 01-11-2022 00:08:10 47.15 Off
2 01-11-2022 00:23:10 47.15 Off
3 01-11-2022 00:38:10 47.15 Off
4 01-11-2022 00:58:10 47.15 Off
5 01-11-2022 01:18:10 47.15 Off
...
32357 24-11-2022 17:48:43 45.40 On
32358 24-11-2022 17:48:52 44.51 On
32359 24-11-2022 17:48:55 44.51 On
32360 24-11-2022 17:48:58 44.51 On
32361 24-11-2022 17:48:58 44.51 On
На этом этапе мы можем использовать обработку текста, такую как csv, или добавить скобки json.
for /f "tokens=1,2,3,4,5 delims= " %%a In ('Findstr /C:"O" battery.txt') do echo csv is "%%a,%%b,%%c,%%d,%%e">output.txt
...
csv is "32357,24-11-2022,17:48:43,45.40,On"
csv is "32358,24-11-2022,17:48:52,44.51,On"
csv is "32359,24-11-2022,17:48:55,44.51,On"
csv is "32360,24-11-2022,17:48:58,44.51,On"
csv is "32361,24-11-2022,17:48:58,44.51,On"
Итак, запрос для JSON (не моя сильная сторона, поэтому вам может потребоваться улучшить мой код, поскольку я не знаю, чего ожидает монго)
вот скидываю pdf на аккум.бат
{"line_id":1,"created":{"date":"01-11-2022"},{"time":"00:08:10"},{"Voltage":"47.15"},{"State","Off"}}
{"line_id":2,"created":{"date":"01-11-2022"},{"time":"00:23:10"},{"Voltage":"47.15"},{"State","Off"}}
{"line_id":3,"created":{"date":"01-11-2022"},{"time":"00:38:10"},{"Voltage":"47.15"},{"State","Off"}}
{"line_id":4,"created":{"date":"01-11-2022"},{"time":"00:58:10"},{"Voltage":"47.15"},{"State","Off"}}
{"line_id":5,"created":{"date":"01-11-2022"},{"time":"01:18:10"},{"Voltage":"47.15"},{"State","Off"}}
{"line_id":6,"created":{"date":"01-11-2022"},{"time":"01:33:10"},{"Voltage":"47.15"},{"State","Off"}}
{"line_id":7,"created":{"date":"01-11-2022"},{"time":"01:48:10"},{"Voltage":"47.15"},{"State","Off"}}
{"line_id":8,"created":{"date":"01-11-2022"},{"time":"02:03:10"},{"Voltage":"47.15"},{"State","Off"}}
{"line_id":9,"created":{"date":"01-11-2022"},{"time":"02:18:10"},{"Voltage":"47.15"},{"State","Off"}}
{"line_id":10,"created":{"date":"01-11-2022"},{"time":"02:37:12"},{"Voltage":"47.15"},{"State","Off"}}
это немного медленнее, чем в чистой консоли, поэтому давайте запустим его вслепую, добавив @, это все равно займет время, так как мы работаем с обычным текстом, поэтому ожидайте значительную задержку для 32 000+ строк = 2 + 1/2 минуты на мой комплект
pdftotext -layout -nopgbrk -x 0 -y 60 -W 700 -H 800 -fixed 8 "%~1" battery.txt
echo Heading however you wish it for json perhaps just opener [ but note only one redirect chevron >"%~dpn1.txt"
for /f "tokens=1,2,3,4,5 delims= " %%a In ('Findstr /C:"O" battery.txt') do @echo "%%a": { "Date": "%%b", "Time": "%%c", "Voltage": %%d, "Ignition": "%%e" },>>"%~dpn1.txt"
REM another json style could be { "Line_Id": %%a, "Date": "%%b", "Time": "%%c", "Voltage": %%d, "Ignition": "%%e" },
REM another for an array can simply be [%%a,"%%b","%%c",%%d,"%%e" ],
echo Tailing however you wish it for json perhaps just final closer ] but note double chevron >>"%~dpn1.txt"
Чтобы увидеть прогресс, измените @echo {
на @echo %%a&echo {
Таким образом, через минуту или около того однако это, как правило, добавляет лишнюю минуту для всей этой активности на дисплее! до того, как окно закроется в знак завершения.
Файлы PDF не содержат информации о том, как должен располагаться текст. Все, что у него есть, это положение текста на странице. Для такого инструмента, как pdfplumber, все, что он может сделать, это угадать, в каком порядке он должен идти, глядя на координаты X и Y текста на странице.