> 백엔드 개발 > 파이썬 튜토리얼 > 주말 코딩: PDF 급여명세서를 단일 CSV 보고서로 전환

주말 코딩: PDF 급여명세서를 단일 CSV 보고서로 전환

Susan Sarandon
풀어 주다: 2024-12-25 22:20:17
원래의
124명이 탐색했습니다.

PDF 파일로 프로그래밍해 본 적이 있나요? 저와 함께 Python 스크립트를 작성해 보세요!

Weekend Coding: Turn PDF Payslips Into a Single CSV Report

다음 블로그 게시물에서 보실 수 있듯이 저는 지금 금융 지식의 시대에 살고 있습니다. 연말이 다가옴에 따라 내 수치를 살펴보고 싶었습니다. 내가 낸 세금은 얼마나 됩니까? 당직 교대근무로 얼마를 벌었나요? 여러 PDF 파일은 이 데이터를 보는 가장 편안한 방법이 아니며 Excel에서 사용할 수 있는 단일 CSV 파일을 원했습니다.

많은 훌륭한 개발자들처럼 저도 수동으로 숫자를 입력하기에는 너무 게을러서 스크립트를 작성했습니다. 프로그래밍을 좋아하신다면 저와 함께 모험을 떠나보세요! 기분이 좋지 않다면 급여명세서 구조에 맞게 코드를 조정하는 방법을 알려드리겠습니다. :D

Weekend Coding: Turn PDF Payslips Into a Single CSV Report
This script receives a directory with payslip PDFs and returns a CSV file with the desired data

계획

main.py:
# translate 1 pdf to 1 dict
# loop over the pdf dir
# save all dicts to 1 json file
# translate json report to csv report
로그인 후 복사
로그인 후 복사
로그인 후 복사

보고서에서 원하는 필드를 결정하는 것을 포함하여 PDF를 읽는 코드를 작성하는 것부터 시작하겠습니다. 급여명세서 구조에 맞게 조정해야 할 부분입니다. 그것이 파악되면 전체 급여명세서 디렉토리를 반복할 것입니다.

세 번째 단계에서는 PDF와 CSV 사이에 JSON 보고서라는 추가 단계를 추가하기로 결정했습니다. 모든 것이 제대로 작동하는 것을 확인하면 해당 파일의 사용을 제거하겠습니다.

마지막으로 해당 JSON 데이터를 CSV 파일로 변환하겠습니다. 그런 다음 해당 CSV를 Google 스프레드시트('다음으로 열기' 클릭) 또는 Excel(지침은 여기에서 찾을 수 있음)로 쉽게 변환할 수 있습니다.

쉽고 좋은 계획이지만 어떻게 진행되는지 아시죠? 그 과정에서 문제가 발견됩니다... 상황이 복잡해질 수 있는 부분이 무엇인지 추측할 수 있나요?

시작하기 전에 중요한 사항: 급여 명세서를 비공개로 유지하세요! 프로젝트를 GitHub에 업로드하는 경우 개인 정보를 공유하지 마세요! 이를 위해 .gitignore를 사용할 수 있습니다:

/payslips_pdf
pdf_rows.txt
report.json
report.csv
로그인 후 복사
로그인 후 복사

시작해볼까요?

Weekend Coding: Turn PDF Payslips Into a Single CSV Report

PDF 파일 읽기

먼저 PDF를 읽고 모든 행을 인쇄하겠습니다. 그렇게 하면 각 행에 무엇이 나타나는지 알 수 있습니다. 이 작업은 한 번만 수행하면 되며(보고서는 한 달에 한 번 또는 1년에 한 번 생성됨) 보고서의 일부가 아니므로 별도의 파일로 생성하겠습니다.

새 Python 파일(저는 pdf_to_txt.py라고 함)을 만드는 것으로 시작하고 pdf를 읽고 결과를 .txt 파일로 인쇄하는 함수를 작성합니다.



이는 작동하지만 보다 사용자 친화적으로 만들기 위해 3가지 변경 사항이 있습니다.
  • 파일 경로를 명령줄 인수로 가져오면 사용자가 코드를 건드리지 않고도 실행할 수 있습니다.
  • 사용자가 명령을 잘못 실행한 경우를 대비하여 오류 잡기 지침을 추가하세요. (경고색을 추가했는데 꼭 안하셔도 됩니다)

  • 메인 스크립트에서도 PDF 파일을 읽어드릴 테니 이 기능을 그쪽으로 옮기시면 더 좋습니다.

한번 해보세요! 올바른 인수와 잘못된 인수를 사용하여 명령을 실행해 보세요. :)


py ./main.py를 실행하면 프로젝트 디렉토리에 pdf_rows.txt라는 새 파일이 표시됩니다.
<script></script> <script></script> <script></script>
(걱정하지 마세요. 이것은 내 데이터가 아닙니다. 아래 이미지의 급여명세서 예시를 기반으로 합니다.)

PDF 데이터 처리

이제 PDF가 읽혀지는 구조를 알았으므로 원하는 값을 낚시할 수 있습니다. 제 경우에는 제가 관심을 보인 정보는 다음과 같습니다.

Weekend Coding: Turn PDF Payslips Into a Single CSV Report

표 내부에는 데이터(매월 달라질 수 있는 카테고리)가 있고 표 외부에는 데이터가 있습니다.

테이블 외부 데이터:

지급 기간 — 19행에서 확인 가능

총 지불 — 이 항목은 지불 목록 다음에 나타나고 "총 지불"이라는 제목이 없기 때문에 규칙을 찾기가 까다로웠습니다.

앞서 언급한 바와 같이 결제공제는 다를 수 있으며 매달 동일하지는 않습니다. 따라서 총 급여는 달마다 다른 행에 나타날 수 있습니다.

직원 이름 바로 뒤에 표시되는 것을 확인하고 이를 사용했습니다. 먼저 하드 코딩하여 추가한 후 나중에 외부에서 가져옵니다.

Nett Pay: 이 방법은 쉽습니다. 17행에 나와 있습니다.

테이블에 없는 값을 함수로 모았습니다.


테이블 내부의 데이터

결제 및 공제 세부정보: 이 부분이 정말 흥미로웠어요! for 루프에서 몇 밀리초를 절약하기 위해 행 배열을 자르는 것부터 시작하겠습니다. 그런 다음 목록 항목

과 다른 행

을 구별해야 했습니다. 전체 파일 내에서 목록 항목만 이 규칙과 일치하는 것으로 확인되었습니다. 알파벳 문자로 시작하고 숫자로 끝나야 합니다 에는 공백이 포함되어 있습니다(마지막 조건은 my
에서 잘못된 행을 필터링하는 것입니다). 급여명세서는 필요하지 않을 수도 있습니다).

<script></script> <script></script>
이제 라인 그룹이 있으므로 이를 처리하여 JSON 개체에 저장해 보겠습니다. 이 시점에서는 지불인지 공제인지는 신경 쓰지 않습니다.

예를 들어 연금 항목을 살펴보겠습니다.

main.py:
# translate 1 pdf to 1 dict
# loop over the pdf dir
# save all dicts to 1 json file
# translate json report to csv report
로그인 후 복사
로그인 후 복사
로그인 후 복사

잔액(오른쪽 숫자)은 신경 쓰지 않지만 코드는 중요합니다(G는 총 급여에서 공제됨을 의미 - 세전) — 그리고 N은 세금 후 Nett 급여에서 공제됨을 의미합니다. 따라서 이상적으로는 json_obj["Pension (G)"]=150.00이 됩니다.

공백을 사용하여 선을 분할하겠습니다. 중복된 공백이 있으면 좋습니다. 이렇게 하면 두 단어 사이의 공백 분할과 두 필드 사이의 공백 분할을 구별할 수 있습니다.

설명:

첫 번째 이중 공백을 찾아 이를 통해 분할하겠습니다.

코드:

설명의 길이에 따라 공백의 양이 달라지므로 몇 개나 있는지 미리 알 수 없으므로 lstrip()도 사용하겠습니다. 이제 줄의 나머지 부분은 공백이 아닌 문자로 시작됩니다.

모든 목록 항목에 코드가 있는 것은 아니므로 줄이 코드로 시작하는지 아니면 숫자로 시작하는지 확인하고 싶습니다. 코드인 경우 — ()(여는 괄호 앞의 공백 포함)로 묶고 설명 문자열에 첨부합니다. 그렇지 않다면 아무것도 추가하지 마세요.

금액:

코드가 있다면 제거할 공간이 더 많아질 것입니다. 그렇지 않은 경우 라인에 두 가지 금액, 즉 월별 금액과 잔액

이 포함될 수 있습니다.

제가 확인한 4가지 사례는 다음과 같습니다.

/payslips_pdf
pdf_rows.txt
report.json
report.csv
로그인 후 복사
로그인 후 복사

카테고리와 코드를 추출한 후 다음이 남습니다.

PENSION     G   150.00   587.49
로그인 후 복사

2~3번 사례를 다루기 위해 양을 구분하는 공백의 색인을 찾아 꼬리를 잘라냅니다. 공백이 없는(일명 꼬리 없음) 첫 번째 경우에도 작동합니다.

사례 4를 다루기 위해 행에 단일 금액이 있는 두 가지 유형의 범주 간의 차이에 의존합니다. 첫 번째 유형은 급여와 유사하며 금액을 저장하려는 경우이고 두 번째 유형은 다음과 같습니다. 세금 원천징수 – 우리는 이를 무시하고 싶습니다. 차이점은 공제만이 표의 연간 잔액을 추적한다는 것입니다. 그래서 저는 -를 확인하고 있습니다.

모두 합하면 다음과 같습니다.

JSON 파일에 쓰기


이것은 필수 단계가 아닙니다. 값을 내보내지 않고도 JSON 개체로 작업할 수 있습니다. 적어도 코딩 단계에서는 어떻게 보이는지 보는 것이 더 좋습니다.

여러 PDF 파일로 확장

이 단계에서 전용 섹션을 얻는 유일한 이유는 pdf_to_dict를 for 루프로 래핑하면 불쾌한 놀라움이 드러나기 때문입니다. 이를 시연하기 위해 iterate_over_pdfs()라는 함수를 만들었습니다.
<script></script> <script></script> <script></script>
이는 파일 목록이 알파벳 순서로 정렬되어 10이 2 앞에 나타나기 때문에 발생합니다. 보고서 항목을 시간순으로 표시하는 것은 단지 있으면 좋은 기능이 아니라 중요한 것으로 간주될 수 있습니다. 그러므로 우리는 그것을 고쳐야 합니다!

원래는 파일 이름을 바꿔야 한다고 생각했는데(Payslip1.pdf -> Payslip01.pdf) 더 나은 해결 방법이 있습니다.


파일 이름 목록을 길이별로 정렬하면 2 다음에 10이 나타납니다. 마지막 줄에서 b''을 제거하기 위해 이름을 디코딩했습니다. 기본 구조.

CSV 보고서 만들기

지불 및 공제 항목은 급여명세서마다 다를 수 있으므로 이 섹션은 단순한 번역 이상의 의미를 갖습니다. CSV는 관계형 데이터 세트입니다. 즉, 지불 및 공제의 모든 범주를 미리 알아야 하고, 급여 명세서가 존재하지 않는 경우 해당 항목을 비워 두어야 합니다. 반면에 JSON은 비관계형이며 각 항목은 해당 키를 지정합니다.

이를 염두에 두고 CSV 보고서의 첫 번째 단계는 카테고리를 수집하는 것입니다. 모든 카테고리.

카테고리 수집:


이제 언뜻 보면 Set을 사용하는 것이 좋겠다고 생각할 수도 있습니다. 왜냐하면 우리는 모든 카테고리가 한 번만 나타나기를 원하기 때문입니다. 나는 그것을 시도했다. 문제는 세트가 목록에 없다는 점이며, 원래 급여명세서에 나타나는 항목의 순서를 일치시키는 것이 중요하다고 생각합니다. 목록을 사용할 때 항목을 추가하기 전에 목록에 항목이 있는지 확인하는 것을 잊지 마세요.


이제 이것을 알아냈습니다. 앞서 어떤 항목 목록이 지불이고 어떤 항목이 공제인지 신경 쓰지 않는다고 말한 것을 기억하십니까? 글쎄, 이제 우리는 걱정합니다! 별도로

필요
는 않지만 급여명세서 보고서에는 모든 지급액이 오른쪽에, 모든 공제액이 왼쪽에 혼합되지 않고 표시될 것으로 예상됩니다.

각 급여명세서에는 서로 다른 목록 항목이 있을 수 있지만 일부는 항상 존재합니다(왜냐하면 귀하는 항상 세금을 납부해야 하기 때문입니다 ;)). 우리는 이것을 우리의 이익으로 사용할 수 있으며 PAYE를 공제의 시작으로 표시할 수 있습니다! (PAYE는 아일랜드에만 있는 것으로 확신하므로 급여명세서와 일치하도록 변경해야 합니다)

마지막으로, 지불금과 공제액을 분리하는 것은 아무 소용이 없기 때문에 단일 목록을 반환합니다. 분할은 지불금이 오른쪽에 표시되고 공제액이 왼쪽에 표시되도록 하기 위한 것이었습니다.

CSV 테이블 채우기:


이제 카테고리가 있으므로 CSV 테이블을 채울 수 있습니다.

각 급여명세서는 행으로 구성되며, 각 행에는 쉼표로 구분된 특정 순서의 필드가 있습니다. 목록의 필드를 구성한 다음 결합하는 것이 더 쉽다는 것을 알았습니다. 카테고리에는 표시되지만 급여명세서에는 표시되지 않는 필드는 비어 있습니다.


<script></script> 마지막으로 CSV 파일에 작성하겠습니다.<script></script> <script></script> <script></script> <script></script>
그러면 모든 급여명세서가 포함된 멋진 CSV 보고서를 갖게 됩니다!

VS 확장 RainbowCSV(또는 다른 IDE와 유사한 버전)를 다운로드하면 더 쉽게 읽을 수 있습니다

.json 파일 사용 제거

일단 제대로 작동한다는 것을 알게 되면 JSON 파일에 쓰거나 읽을 필요가 없습니다. JSON 개체를 직접 사용할 수 있습니다.

json_object를 사용하는 대신(json_object = json.dumps(json_payslips)에서와 같이) – json_payslips를 직접 사용합니다.

  1. 쓰기: report.json에 쓸 필요가 없습니다. 이 섹션을 제거할 수 있습니다.

  2. 읽기: json_payslips를 json_to_csv() 함수에 직접 전달하세요.

직원의 이름을 인수로 가져오기

대본이 준비되면 동료 및 친구들과 공유하고 싶을 것입니다! 좋은 사용자 경험을 위해 직원에게 코드를 열도록 요청하는 대신 명령줄에서 직원 이름을 내보내도록 하겠습니다.

인수 읽기

사용자가 직원 이름을 입력했다고 가정하고 행복한 경로부터 시작하고 이를 사용하는 코드를 추가하겠습니다.

pdf_to_dict()에서는 EMPLOYEE_NAME = "IFAT NEEUMANN"을 하드 코딩하는 대신 직원 이름 = sys.argv[1] 인수에서 읽습니다. sys를 가져오는 것을 잊지 마세요!

이제 다른 시나리오를 생각해 보겠습니다.

직원 이름이 지정되지 않았습니다

사용자가 직원 이름을 입력하지 않으면 어떻게 되나요? 가능한 한 빨리 이를 확인하고 알리고 싶습니다!

따라서 메인 함수의 첫 번째 줄에 체크를 추가하겠습니다. 이제 직관은 거기에서 Employee_name 변수를 초기화하는 것입니다. 하지만 이렇게 하면 이 변수를 사용하는 함수에 도달할 때까지 함수 속성 버블링이 발생하게 되며 매우 깔끔한 접근 방식이라고 생각하지 않습니다.


마지막으로 이 필드에 액세스해 보고 거기에 없으면 확인하겠습니다.


main.py:
# translate 1 pdf to 1 dict
# loop over the pdf dir
# save all dicts to 1 json file
# translate json report to csv report
로그인 후 복사
로그인 후 복사
로그인 후 복사

예외를 추가한다는 것은 print_warning() 함수가 main.py로 이동한다는 것을 의미합니다. 그렇지 않으면 오류가 발생합니다.

따옴표 없는 직원 이름


명령줄 인수가 공백으로 분할되므로 사용자에게 이름을 따옴표로 묶어달라고 요청합니다. 우리가 기대하는 유일한 인수는 직원 이름이므로 다른 인수가 있는 경우 따옴표를 사용하지 않았음을 알고 이를 알릴 수 있습니다.



인용 요구 사항을 건너뛰고 인수를 반복하여 사용자 이름의 모든 부분을 수집할 수 있지만 이 접근 방식은 불필요하게 복잡해집니다.

급여명세서에 직원 이름이 나오지 않아요


급여 명세서에 기재된 직원의 이름이 없으면 총 급여를 확인할 수 없습니다.

불일치 여부를 가장 빨리 식별할 수 있는 시점은 PDF를 읽을 때입니다. 그러므로 — pdf_to_dict() 함수 시작 부분에 검사를 추가하세요:
<script></script> <script></script> <script></script> <script></script>
(sys.argv[1]이 텍스트에 없는 경우보다) 읽기가 더 쉽기 때문에 Employee_name = sys.argv[1]을 이 함수로 옮겼습니다. 그런 다음 이를 get_fixed_values()에 전달합니다.

마지막으로 main 함수에서 오류를 다시 잡아냅니다.


마무리하려면 README 파일을 새로운 지침으로 업데이트하는 것을 잊지 마세요.

전체 스크립트


급여 명세서를 가지고 놀 때 사용할 수 있는 전체 코드는 다음과 같습니다.


Weekend Coding: Turn PDF Payslips Into a Single CSV Report
https://cupofcode.blog/
당신이 이것을 즐겼기를 바랍니다! 또 다른 주말 코딩 프로젝트에 관심이 있으신가요? 자동 이메일 전송 블로그 게시물을 확인해 보세요!

블로깅은 취미이기 때문에 즐겁게 시간과 돈을 쓰고 있습니다. 이 블로그 게시물이 마음에 드셨다면 팁통에 1유로를 넣어주시면 알려드리겠습니다 :) 많은 응원 부탁드립니다! <script></script> <script></script>

위 내용은 주말 코딩: PDF 급여명세서를 단일 CSV 보고서로 전환의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿