(이것은XY 문제, 마지막에 컨텍스트에 대한 자세한 내용)
장 제목을 기준으로 PDF를 프로그래밍 방식으로 분할하는 방법이 있습니까? 그건
이 PDF에서 2개의 PDF를 생성합니다. 하나는 "XY" 부분까지 모든 것을 포함하고 두 번째는 다른 모든 것을 포함합니다.
나페이지 번호를 기준으로 PDF를 분할하는 방법 알아보기, 그러나 더 많은 "의미"를 사용할 수 있습니까?
(간단히 말하면 원래 질문은 다음과 같습니다. NSF는 한 문서에 참조 목록을 갖고 다른 문서에 설명을 갖고 싶어하며 LaTeX/pandoc을 사용하여 문서를 생성하고 있으므로 모든 내용을 포함하고 싶습니다. 하나의 문서에서 사용하는 것이 더 간단하고 링크는 중요하지 않습니다.)
답변1
pdftk
나는 이런 유형의 작업 에 사용하는 것을 좋아합니다 .
Latex를 사용하여 기본 문서를 생성하면 다음과 같을 것입니다:
\documentclass{report}
\usepackage{blindtext} % For lorem ipsum text
\usepackage{hyperref} % Turns chapters/sections into bookmarks
\begin{document}
\chapter{First Chapter}
\Blindtext[10]
\section{Subsection of chapter 1}
\Blindtext[3]
\chapter{Second Chapter}
\Blindtext[20]
\chapter{Third Chapter}
\Blindtext
\pdfbookmark{Example bookmark}{A}
\Blindtext
\end{document}
을 실행하면 pdflatex
각 장에 대한 자동 북마크, 섹션 1.1에 대한 심층 북마크, 이후에 대한 수동 북마크 및 많은 lorem ipsum 구절이 포함된 13페이지 PDF가 생성됩니다.
이제 PDF 파일이 있으므로 이를 사용하여 pdftk
이에 대한 통찰력을 얻을 수 있습니다. 자료가 너무 많아서 흥미로운 부분만 잘랐습니다.
$ pdftk sample.pdf dump_data
InfoBegin
...
NumberOfPages: 13
BookmarkBegin
BookmarkTitle: First Chapter
BookmarkLevel: 1
BookmarkPageNumber: 1
BookmarkBegin
BookmarkTitle: Subsection of chapter 1
BookmarkLevel: 2
BookmarkPageNumber: 3
BookmarkBegin
BookmarkTitle: Second Chapter
BookmarkLevel: 1
BookmarkPageNumber: 5
BookmarkBegin
BookmarkTitle: Third Chapter
BookmarkLevel: 1
BookmarkPageNumber: 11
BookmarkBegin
BookmarkTitle: Example bookmark
BookmarkLevel: 1
BookmarkPageNumber: 12
PageMediaBegin
...
레이블을 클릭하면 BookmarkBegin
북마크가 있다는 것을 알 수 있습니다. 그것을 보면 BookmarkTitle: X
우리는 1부에 도달했다는 것을 알 수 있습니다 X
. BookmarkPageNumber:
각 북마크에는 연관된 북마크가 있습니다. 이것을 분할에 사용할 수 있습니다. BookmarkLevel
분할하려는 수준(장, 섹션, 하위 섹션)을 필터링하는 데 사용할 수도 있습니다 .
챕터 1과 챕터 2로 분할하고 싶다고 가정해 보겠습니다. 4페이지 이전에 분할을 추가해야 한다는 데이터를 보면 다음과 같습니다.
BookmarkTitle: Second Chapter
BookmarkPageNumber: 5
이제 페이지 번호가 있으므로 이를 pdftk
분할에 사용할 수 있습니다. 여기에는 실제로 cat
특정 페이지에서의 사용이 포함됩니다.
pdftk sample.pdf cat 1-4 output sample-1.pdf
pdftk sample.pdf cat 5-end output sample-2.pdf
보다 일반적인 접근 방식을 취하여 .pdf라는 pdf 스크립트로 작성해 보겠습니다 sample.pdf
. 각 고급 북마크에서 PDF를 분할해 보겠습니다(해당 부분 필터링).
먼저 북마크 태그를 좀 더 쉽게 구문 분석할 수 있는 형식으로 변환하여 무언가를 쓸 수 있도록 하겠습니다. awk
(다른 이름으로 저장하겠습니다 parser.awk
)
#!/bin/awk -f
BEGIN {
FS=": "
OFS=";"
}
/^BookmarkBegin/ {
if (this_level > 1) { # Only handle high-level sections
next
}
if (this_page == "" || this_title == ""){
next
}
if (last_page != "" && last_title != "") {
print last_title, last_page, this_page-1
}
last_title=this_title
last_page=this_page
this_title=this_page=this_level=""
}
/^BookmarkTitle:/ {
this_title=$2
}
/^BookmarkPageNumber:/ {
this_page=$2
}
/^BookmarkLevel:/ {
this_level=$2
}
END {
print last_title, last_page, this_page-1
print this_title, this_page, "end"
}
여기서는 헤더에 a가 포함되어 있지 않다고 가정하므로 ;
이를 출력 구분 기호로 사용합니다. 스크립트는 다음을 출력합니다.
- 각 부분의 명칭
- 이 섹션의 홈 페이지
- 이 섹션의 마지막 페이지입니다.
$ pdftk sample.pdf dump_data | awk -f parser.awk
First Chapter;1;4
Second Chapter;5;10
Third Chapter;11;11
Example bookmark;12;end
이제 각 줄을 반복하고 pdftk
bash에서 이것을 호출해 보겠습니다.
#!/bin/bash
sequence=1
pdftk sample.pdf dump_data | awk -f parser.awk | \
while IFS=";" \
read -r title start end
do
pdftk sample.pdf cat "$start"-"$end" output sample-$sequence-"$title".pdf
sequence=$((sequence+1))
done
이로 인해 다음이 남습니다.
$ ls *.pdf
'sample-1-First Chapter.pdf'
'sample-2-Second Chapter.pdf'
'sample-3-Third Chapter.pdf'
'sample-4-Example bookmark.pdf'
sample.pdf
이에 대한 한 가지 제한 사항은 동일한 페이지에 여러 개의 북마크가 있거나 매우 적은 북마크가 있는 경우 약간 혼란스러울 수 있다는 것입니다.
답변2
작년에 저는 Python 라이브러리를 사용하여 py_pdf_parser
비슷한 목표를 달성했습니다. pdfplumber
게다가 MathPix API(유료이지만 최소한의 비용)를 사용하여 Latex로 최종 변환했습니다.
여기에서 내 스크립트를 확인하여 도움이 되는지 확인할 수 있습니다.https://github.com/sekerez/linear_algebra_done_right/blob/main/problems/extract_problems_from_pdf_book.py이 스크립트는 책에 있는 모든 문제를 추출하여 연습문제 번호와 문제 번호를 기준으로 데이터 구조로 깔끔하게 정리합니다. 단 몇 줄의 코드만으로 이런 작업을 수행할 수 있다는 사실이 놀랍습니다.
사용 사례에 맞게 스크립트를 조정해야 합니다. 각 PDF는 매우 다르기 때문에 기계가 PDF를 처리하기가 매우 어렵습니다. 따라서 PDF 형식을 기반으로 자신만의 스크립트를 수동으로 작성해야 합니다.
답변3
스튜어트의 대답거의 모든 도구가 제공되었지만 솔루션에 두 가지 중요한 편집을 수행했습니다.
- 사용일관성pdf디렉토리를 유지하십시오(pdftk는 디렉토리를 제거합니다).
- 명령이 파일을 장 수만큼 많은 장으로 분할하는 대신 파일을 두 부분으로 분할하도록 합니다.
parser.awk
소스 코드가 호출되고 source.pdf
문서를 분할하려는 섹션을 "부록"이라고 가정하고 Stewarts가 공유한 내용을 재사용하면 다음이 제공됩니다.
pdftk source.pdf dump_data | \
awk -f parser.awk | \
grep Appendix | \
{
IFS=";" ; \
read -r title start end; \
./cpdf source.pdf 1-"`expr $start - 1`" -o A.pdf; \
./cpdf source.pdf "$start"-"$end" -o B.pdf;
}
이것
- 파일의 메타데이터를 덤프합니다.
- 해당 비트(
title ; page start ; page ends
)를 추출하고, - 부록의 관련 부분을 잡고,
read
구분 기호를 다음으로 설정하세요 .;
- 제목을
title
변수에 저장하고, 시작 페이지를 에start
, 끝 페이지를 에 저장합니다end
. start - 1
1부터 (부록 시작 전 페이지에 해당)까지의 모든 페이지를A.pdf
,- 문서의 나머지 부분을
B.pdf
.