如何从命令行中将PDF数据从PDF中提取出来?

use*_*838 14 pdf grep pdftotext

我想从这里提取所有行,同时忽略列标题以及所有页面标题,即Supported Devices.

pdftotext -layout DAC06E7D1302B790429AF6E84696FCFAB20B.pdf - \
 | sed '$d'                                                  \
 | sed -r 's/ +/,/g; s/ //g'                                 \
 > output.csv
Run Code Online (Sandbox Code Playgroud)

生成的文件应采用CSV电子表格格式(逗号分隔值字段).

换句话说,我想改进上面的命令,以便输出根本不会制动.有任何想法吗?

Kur*_*fle 21

我也会为你提供另一种解决方案.

虽然在这种情况下该pdftotext方法可以合理地工作,但是可能存在不是每个页面具有相同列宽的情况(如您的相当良好的PDF显示).

在这里,不太知名但非常酷的Free和OpenSource软件Tabula-Extractor是最佳选择.

我自己正在使用直接GitHub结帐:

$ cd $HOME ; mkdir svn-stuff ; cd svn-stuff
$ git clone https://github.com/tabulapdf/tabula-extractor.git git.tabula-extractor
Run Code Online (Sandbox Code Playgroud)

我给自己写了一个非常简单的包装脚本,如下所示:

$ cat ~/bin/tabulaextr

 #!/bin/bash
 cd ${HOME}/svn-stuff/git.tabula-extractor/bin
 ./tabula $@
Run Code Online (Sandbox Code Playgroud)

既然~/bin/在我身上$PATH,我就跑了

$ tabulaextr --pages all                                 \
         $(pwd)/DAC06E7D1302B790429AF6E84696FCFAB20B.pdf \
        | tee my.csv
Run Code Online (Sandbox Code Playgroud)

从所有页面中提取所有表并将其转换为单个CSV文件.

CVS的前十行(总共8727行)如下所示:

$ head DAC06E7D1302B790429AF6E84696FCFAB20B.csv 

 Retail Branding,Marketing Name,Device,Model
 "","",AD681H,Smartfren Andromax AD681H
 "","",FJL21,FJL21
 "","",Luno,Luno
 "","",T31,Panasonic T31
 "","",hws7721g,MediaPad 7 Youth 2
 3Q,OC1020A,OC1020A,OC1020A
 7Eleven,IN265,IN265,IN265
 A.O.I. ELECTRONICS FACTORY,A.O.I.,TR10CS1_11,TR10CS1
 AG Mobile,Status,Status,Status
Run Code Online (Sandbox Code Playgroud)

在原始PDF中看起来像这样:

屏幕示例PDF的第一页顶部

它甚至在最后一页上有这些行,293,右:

 nabi,"nabi Big Tab HD\xe2\x84\xa2 20""",DMTAB-NV20A,DMTAB-NV20A
 nabi,"nabi Big Tab HD\xe2\x84\xa2 24""",DMTAB-NV24A,DMTAB-NV24A
Run Code Online (Sandbox Code Playgroud)

在PDF页面上看起来像这样:

样本PDF的最后一页

TabulaPDF和Tabula-Extractor对于像这样的工作真的很酷!


更新

这是一个ASCiinema截屏视频(您可以在命令行工具的帮助下在Linux/MacOSX/Unix终端上本地下载和重新播放asciinema),主演tabula-extractor:

asciicast

  • 新的基于 Java 的 tabula 版本可以在这里找到:https://github.com/tabulapdf/tabula-java (4认同)

Nob*_*obu 8

正如Martin R 评论的那样tabula-java是新版本tabula-extractor且活跃。1.0.0 于 2017 年 7 月 21 日发布。

下载 jar 文件并使用最新的 java:

java -jar ./tabula-1.0.0-jar-with-dependencies.jar \
    --pages=all \
    ./DAC06E7D1302B790429AF6E84696FCFAB20B.pdf
    > support_devices.csv
Run Code Online (Sandbox Code Playgroud)


Kur*_*fle 5

你想要的是相当容易的,但你也有一个不同的问题(我不确定你是否意识到它......).

首先,您应该-nopgbrk为您的命令添加("没有分页,请!").因为^L否则出现在输出中的这些讨厌的字符不需要在以后过滤掉.

添加一个grep -vE '(Supported Devices|^$)'将删除所有你不想要的行,包括空行或只有空格的行:

pdftotext -layout -nopgbrk                           \
   DAC06E7D1302B790429AF6E84696FCFAB20B.pdf -        \
 | grep -vE '(Supported Devices|^$|Marketing Name)'  \
 | gsed '$d'                                         \
 | gsed -r 's# +#,#g'                                \
 | gsed '# ##g'                                      \
 > output2.csv
Run Code Online (Sandbox Code Playgroud)

但是,你的另一个问题是:

  1. 某些表字段为空.
  2. 出现空字段时,该-layout选项为一系列空格字符,有时甚至是同一行中的两个空格字符.
  3. 但是,文本列在页面之间的间隔不相同.
  4. 因此,您不会从一行到另一行知道您需要将多少空格视为"空CSV字段"(您需要额外的,分隔符).
  5. 因此,对于某些行,您当前的代码将只显示一个,两个或三个(而不是四个)字段,这些字段最终会出现在错误的列中!

有一个解决方法:

  1. 添加-x ... -y ... -W ... -H ...参数以pdftotext逐列裁剪PDF.
  2. 然后用像公用事业组合追加列pastecolumn.

以下命令提取第一列:

pdftotext -layout -x  38 -y 77 -W 176 -H 500  \
          DAC06E7D1302B790429AF6E84696FCFAB20B.pdf - > 1st-columns.txt
Run Code Online (Sandbox Code Playgroud)

这些是第二,第三和第四列:

pdftotext -layout -x 214 -y 77 -W 176 -H 500  \
          DAC06E7D1302B790429AF6E84696FCFAB20B.pdf - > 2nd-columns.txt

pdftotext -layout -x 390 -y 77 -W 176 -H 500  \
          DAC06E7D1302B790429AF6E84696FCFAB20B.pdf - > 3rd-columns.txt

pdftotext -layout -x 567 -y 77 -W 176 -H 500  \
          DAC06E7D1302B790429AF6E84696FCFAB20B.pdf - > 4th-columns.txt
Run Code Online (Sandbox Code Playgroud)

顺便说一句,我被骗了一下:为了得到什么值使用的线索-x,-y,-W-H我第一次为了找到列标题词的精确坐标运行以下命令:

pdftotext -f 1 -l 1 -layout -bbox \
          DAC06E7D1302B790429AF6E84696FCFAB20B.pdf - | head -n 10
Run Code Online (Sandbox Code Playgroud)

如果你知道如何阅读和使用它总是好的pdftotext -h.:-)

无论如何,如何将四个文本文件并排添加为列,中间有适当的CVS分隔符,您应该自己找出答案.或者问一个新问题:-)