teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

4

表現を修正

2020/09/12 16:41

投稿

Daregada
Daregada

スコア11990

answer CHANGED
@@ -45,7 +45,7 @@
45
45
  print("すべての処理が正常に完了しました。")
46
46
  ```
47
47
  追加分:
48
- - PDFファイルの内容により、`PyPDF2.PdfFileReader()`で読み込むさいに「OSError: [Errno 22] Invalid argument」になるものがある。公式のGitHubの以下のページで議論されている(未解決)。
48
+ - PDFファイルの内容により、`PyPDF2.PdfFileReader()`で読み込むさいに「OSError: [Errno 22] Invalid argument」になるものがある。PyPDF2公式のGitHubの以下のページで議論されている(未解決)。
49
49
 
50
50
  [A certain PDF File triggers OSError: [Errno 22] Invalid argument · Issue #530 · mstamy2/PyPDF2](https://github.com/mstamy2/PyPDF2/issues/530)
51
51
 

3

PDFファイル自体に問題があるという補足を追加

2020/09/12 16:41

投稿

Daregada
Daregada

スコア11990

answer CHANGED
@@ -43,4 +43,33 @@
43
43
  odd_object.close()
44
44
  even_object.close()
45
45
  print("すべての処理が正常に完了しました。")
46
- ```
46
+ ```
47
+ 追加分:
48
+ - PDFファイルの内容により、`PyPDF2.PdfFileReader()`で読み込むさいに「OSError: [Errno 22] Invalid argument」になるものがある。公式のGitHubの以下のページで議論されている(未解決)。
49
+
50
+ [A certain PDF File triggers OSError: [Errno 22] Invalid argument · Issue #530 · mstamy2/PyPDF2](https://github.com/mstamy2/PyPDF2/issues/530)
51
+
52
+ 先頭の発言の「This file」のリンクからダウンロードした`NTB - LOI.pdf`(印刷された書類をスキャンしたっぽい内容)を`PyPDF2.PdfFileReader()`で読み込むと、確かに「OSError(以下略)」が発生する。質問者がスキャンで作成したPDFファイルも、これと同じ問題が起きている可能性が高い。なお、こちらで検証に使っていたPDFファイルは、印刷した文書をスキャンしたものではなく、Wordで作成した文書を直接PC上でPDF化したものだった。
53
+
54
+ とりあえずの対策として、上記のスレッドでは、GhostScript(gs)を使ってPDFファイルを書き換えるためのコマンドラインが提案されている。
55
+
56
+ > gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/printer -dNOPAUSE -dQUIET -dBATCH -sOutputFile="出力ファイル名" "入力ファイル名"
57
+
58
+ あいにくWindowsにGhostScriptを入れていなかったので、仮想Linuxマシンで上記のコマンドラインで変換を行なったところ、
59
+ ```terminal
60
+ $ gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/printer -dNOPAUSE -dQUIET -dBATCH -sOutputFile="output.pdf" "input.pdf"
61
+ **** Error: An error occurred while reading an XREF table.
62
+ **** The file has been damaged. This may have been caused
63
+ **** by a problem while converting or transfering the file.
64
+ **** Ghostscript will attempt to recover the data.
65
+ **** However, the output may be incorrect.
66
+ ```
67
+ とエラーを吐いたものの、変換後のPDFファイルは問題なく`PyPDF2.PdfFileReader()`で読み込むことができた。なお、PDFビューアーアプリでは、どちらのPDFファイルも表示できている。
68
+
69
+ ということで、
70
+
71
+ 0. 現在使っているPDFファイルではなく、Wordなどの文書を直接PDF化したものを用意して、コードの動作確認を行なう。
72
+ 0. 最終目的であるスキャンされたPDFファイルのマージを行なうために、GhostScriptのダウンロードとインストールを行なう。
73
+ 0. gsコマンドが利用可能になったら、上記のコマンドラインで変換を試み、生成されたPDFファイルを使って(動作確認済みの)コードでマージを行なう。
74
+
75
+ という手順が必要でしょう。

2

余分なPDFファイルがあっても動作するよう修正

2020/09/12 16:40

投稿

Daregada
Daregada

スコア11990

answer CHANGED
@@ -3,28 +3,29 @@
3
3
  - `pdfwriter`に書き込みを行なう`addPage()`は代入ではなくメソッド呼び出しなので、それに見合う形にする。
4
4
  - 偶数ページのページ数は、奇数ページのページ数と同じか、1ページ少なくなるか(1,3,5ページと2,4ページなど)のどちらかである。1ページ少なくなる場合、`getPage()`しないように`even_pdf.numPages`を使ったif文で処理する。
5
5
 
6
- 残った問題点は、
6
+ ~~残った問題点は、~~
7
- - カレントディレクトリに存在するPDFファイルが2個以外のときの処理。たとえば、1個だけある場合や、3個以上ある場合にどうするか。現在は`ps.listdir()`の末尾2個だけが処理される。
7
+ - ~~カレントディレクトリに存在するPDFファイルが2個以外のときの処理。たとえば、1個だけある場合や、3個以上ある場合にどうするか。現在は`os.listdir()`の末尾2個だけが処理される。~~
8
8
 
9
+ globを使って「even_*.pdf」と「odd_*.pdf」をそれぞれ別個にリストに読み込み、それぞれのリストの要素が1のときだけ続く処理を行なうように変更した。これで、他のPDFファイル(以前作成したmerged.pdfなど)が存在しても動作する。
10
+
9
11
  ```Python
12
+ import glob
13
+ import sys
10
14
  import PyPDF2
11
- import os
12
15
 
13
- pdflist = []
14
- for filename in os.listdir(os.getcwd()):
16
+ even_list = glob.glob("even_*.pdf")
15
- if filename.endswith(r".pdf"):
17
+ odd_list = glob.glob("odd_*.pdf")
16
- pdflist.append(filename)
18
+ if len(even_list) != 1 or len(odd_list) != 1:
19
+ print("1組のPDFファイル(even_*.pdf, odd_*pdf)になっていません")
20
+ sys.exit(1)
17
21
 
18
- pdflist.reverse()
19
- print(pdflist)
20
-
21
- odd_file_name = os.getcwd() + "\" + pdflist[0]
22
+ odd_file_name = odd_list[0]
22
- print(odd_file_name)
23
+ print("odd file: " + odd_file_name)
23
24
  odd_object = open(odd_file_name, "rb")
24
25
  odd_pdf = PyPDF2.PdfFileReader(odd_object)
25
26
 
26
- even_file_name = os.getcwd() + "\" + pdflist[1]
27
+ even_file_name = even_list[0]
27
- print(even_file_name)
28
+ print("even file: " + even_file_name)
28
29
  even_object = open(even_file_name, "rb")
29
30
  even_pdf = PyPDF2.PdfFileReader(even_object)
30
31
 
@@ -39,5 +40,7 @@
39
40
  pdfoutput = open(r"merged.pdf", "wb")
40
41
  pdfwriter.write(pdfoutput)
41
42
  pdfoutput.close()
43
+ odd_object.close()
44
+ even_object.close()
42
45
  print("すべての処理が正常に完了しました。")
43
46
  ```

1

補足を追加

2020/09/12 15:29

投稿

Daregada
Daregada

スコア11990

answer CHANGED
@@ -1,3 +1,11 @@
1
+ - 質問へのコメントでも指摘されているように、`odd_object`と`even_object`のモードは`"rb"にしないと読み込めません。
2
+ - forループで`maxpagenum`という変数が突然出てくる。(偶数ページと奇数ページを比較して、より長くなる可能性がある)`odd_pdf.numPages`に代える。
3
+ - `pdfwriter`に書き込みを行なう`addPage()`は代入ではなくメソッド呼び出しなので、それに見合う形にする。
4
+ - 偶数ページのページ数は、奇数ページのページ数と同じか、1ページ少なくなるか(1,3,5ページと2,4ページなど)のどちらかである。1ページ少なくなる場合、`getPage()`しないように`even_pdf.numPages`を使ったif文で処理する。
5
+
6
+ 残った問題点は、
7
+ - カレントディレクトリに存在するPDFファイルが2個以外のときの処理。たとえば、1個だけある場合や、3個以上ある場合にどうするか。現在は`ps.listdir()`の末尾2個だけが処理される。
8
+
1
9
  ```Python
2
10
  import PyPDF2
3
11
  import os