क्या आप PDF को parse करना चाहते हैं?
(eliot-jones.com)- PDF parsing को स्पष्ट क्रम और संरचना के आधार पर काम करना चाहिए, लेकिन वास्तविक फ़ाइलें अक्सर इस विनिर्देश का पालन नहीं करतीं
- cross-reference (xref) pointer और offset खोजने में तरह-तरह की त्रुटियाँ और असंगतियाँ सामने आती हैं
- व्यवहार में PDF header से पहले मौजूद अनावश्यक डेटा या pointer और offset की गलत स्थिति के कारण कई समस्याएँ पैदा होती हैं
- ऐसे कई मामले भी मिलते हैं जहाँ PDF की xref table खुद अस्पष्ट या गलत format में होती है
- इसलिए प्रमुख viewer non-standard PDF files तक को सपोर्ट करने के लिए अतिरिक्त logic implement करते हैं
PDF parsing के लिए आदर्श तरीका
- सिद्धांत रूप में PDF parsing एक निश्चित क्रम में आगे बढ़ती है
- फ़ाइल की शुरुआत में version header comment ढूँढा जाता है
- cross-reference (xref) pointer ढूँढा जाता है
- सभी object offsets इकट्ठे किए जाते हैं
- trailer dictionary खोजकर पूरे catalog structure तक पहुँचा जाता है
PDF object का परिचय
- PDF object वह इकाई है जो number, string, dictionary जैसे कई PDF elements को समेटकर रखती है
- हर object
obj/endobjmarker के बीच मौजूद होता है - object आपस में indirect reference (उदाहरण:
16 0 R) के ज़रिए जुड़े होते हैं - फ़ाइल के भीतर object को बाँटने का तरीका लचीला है, लेकिन कुछ object types का indirect reference होना अनिवार्य है
cross-reference offset ढूँढना
- PDF में संरचना के तौर पर cross-reference (xref) table होती है, जो object locations के index की तरह काम करती है
- फ़ाइल के अंत में
startxrefsyntax के साथ एक विशेष byte position pointer के रूप में दी जाती है - यह pointer xref location बताता है, लेकिन spec और वास्तविक फ़ाइलों में अंतर होता है। उदाहरण के लिए
%EOFmarker को मूल रूप से आख़िरी पंक्ति में होना चाहिए, लेकिन वास्तविक PDF में यह अंतिम 1,024 bytes के भीतर कहीं भी हो सकता है - वास्तविक फ़ाइलों में pointer के format errors (
startrefआदि), line break की कमी, और कई तरह के variations मिलते हैं
object offset ढूँढना
- xref table में
xref, object start number, और object count क्रम से आते हैं, और हर object का offset/generation number/status (nयाf) एक पंक्ति में लिखा होता है - कई xref tables हो सकती हैं, या वे
/Preventry के ज़रिए एक-दूसरे से जुड़ी हो सकती हैं
trailer dictionary की स्थिति खोजना
startxrefmarker के ऊपर trailer dictionary मौजूद होती है, जिसमें root object खोजने के लिए ज़रूरी metadata शामिल होता है- root object के आधार पर पूरी संरचना की व्याख्या शुरू की जा सकती है
वास्तविक दुनिया: अप्रत्याशित समस्याएँ
-
PDF spec का पालन न करने वाली फ़ाइलें बहुत हैं, इसलिए सामान्य parser से उन्हें संभालना मुश्किल होता है
-
cross-reference pointer खोज में अक्सर असफल होने वाले मामले
- pointer फ़ाइल के अंत या अंतिम 1,024 bytes में नहीं है
- typo (
startrefआदि) - असामान्य format
-
3,977 वास्तविक PDF samples की जाँच में लगभग 0.5% में xref declaration errors पाए गए
PDF content 0 के अलावा किसी और offset से शुरू होता है
- अगर header से पहले बेकार डेटा (junk) हो, तो सभी byte offsets खिसक जाते हैं और
startxrefposition गड़बड़ा जाती है - header position के आधार पर offsets को फिर से calculate करना पड़ता है, और दोनों positions की जाँच करनी होती है
- यह कुल errors का लगभग 50% हिस्सा बनाता है
xref pointer xref table के बीच में इशारा करता है
- दिया गया offset कभी-कभी xref table के content के ठीक बीच में जा सकता है
- 3,977 samples में से लगभग 5 मामलों में यह पाया गया
pointer xref के पास है
- कई बार pointer बिल्कुल सही नहीं होता, लेकिन xref के ठीक पहले या बाद की whitespace या newline error जितना ही खिसका होता है
pointer सही है लेकिन xref offset गलत है
- xref table में दर्ज offsets खुद भी गलत हो सकते हैं
- कुछ object ही सही हों और बाकी में offset errors हों, ऐसा भी हो सकता है
पहला pointer सही है लेकिन पिछला offset (/Prev) असामान्य है
- PDF को modify करते समय बनने वाले
/Prevpointer में गलत मान (जैसे0) सेव होने के कई मामले मिले हैं
xref table का format असामान्य है
xrefऔर संख्या बिना line break के जुड़े हों, घोषित object से ज़्यादा entries हों, या table के बीच में garbage data शामिल हो — ऐसे कई रूप मिलते हैं- ऐसे मामलों की PdfPig आदि में issue के रूप में बड़ी संख्या में रिपोर्ट हुई है
निष्कर्ष
- specification के अनुसार PDF parsing को एक standardized क्रम में होना चाहिए, लेकिन वास्तविक फ़ाइलों में अक्सर ऐसा नहीं होता, इसलिए parsing में कई तरह की समस्याएँ आती हैं
- व्यावहारिक PDF viewers आम तौर पर non-standard PDF support को बुनियादी क्षमता के रूप में शामिल करते हैं
- इस बार का सार PDF specification (कुल 1300 pages में से 22 pages) के केवल एक हिस्से की parsing पर केंद्रित था
5 टिप्पणियां
इस बार की summary सामग्री PDF specification (कुल 1300 पेज में से 22 पेज) के सिर्फ एक हिस्से की parsing पर आधारित थी <-... 1300 पेज वाकई बेहद विशाल हैं...
वाह..
ईमानदारी से कहें तो, PDF इंसानों द्वारा बनाए गए फ़ॉर्मैटिंग को जितना हो सके उतना सुरक्षित रखने वाला, लोगों के पढ़ने के लिए अनुकूल फ़ॉर्मैट है, और मशीनों के साथ इसकी संगतता सबसे खराब है।
सहमत हूँ। सच कहूँ तो, यह पढ़ने में आसान भी है या नहीं, पता नहीं.. यह बहुत भारी और असुविधाजनक है।
Hacker News राय
जवाब साफ़ है
हक़ीक़त में, मेरा नाम Geoff है, लेकिन आधे resume parser मेरे नाम को अलग-अलग "Geo" और "ff" के रूप में पहचानते हैं
ऐसा PDF में text के जाने के तरीके की वजह से होता है, और यह अलग-अलग source apps में बार-बार होने वाली समस्या है
PDF parsing और PDF content parsing पूरी तरह अलग चीज़ें हैं
PDF file को parse करना भी सिरदर्द है, लेकिन PDF खुद "किसी तय जगह पर कुछ छापो" मॉडल पर आधारित है, इसलिए यह किसी bounding box के अंदर well-defined text जैसा नहीं है; शब्द निकालने के लिए अक्सर यह अनुमान लगाना पड़ता है कि कौन-से glyph एक साथ हैं
अगर आप resume parser की मदद करना चाहते हैं, तो accessibility tree पर ध्यान देना चाहिए
सभी PDF renderer accessibility PDF export नहीं करते, लेकिन accessibility PDF कम-से-कम नाम जैसी चीज़ों को सही ढंग से पढ़ने में मदद कर सकता है
"ff" वाली समस्या शायद non-ASCII characters, जैसे ff ligature, को resume analyzer के ठीक से handle न कर पाने की वजह से है
PDF renderer को ligature न बनाने के लिए configure किया जा सकता है, लेकिन तब text बदसूरत दिख सकता है
ऐसा लगता है कि "चाहिए(should)" शब्द से बहुत ज़्यादा उम्मीद लगाई जा रही है
जब PDF का इस्तेमाल ख़ुद काफ़ी हद तक hostile होता है, तो लोग शायद इतना आगे सोचते ही नहीं
resume को PDF में देने का मकसद ही अक्सर यह होता है कि बीच के बिचौलिये उसे बदल न सकें, और "editing" रोकने के भी कई कारण होते हैं, जैसे image पर box बनाकर कुछ छुपाना, या tables को CSV की जगह PDF में देना ताकि analysis मुश्किल हो जाए
असल में यह तरीका कई बार काफ़ी अच्छा काम करता है, और कुछ apps पहले से यह तरीका इस्तेमाल भी करते हैं
बस समस्या यह रहती है कि दोनों representations, यानी main body और metadata, हमेशा एक-दूसरे से मेल नहीं खाते
सवाल यह भी है कि handwritten scans या दूसरे scanned documents का क्या होगा, अगर scanner और आम घरेलू कंप्यूटर में perfect OCR support न हो
शायद ff के ligature के रूप में render होने से ही यह समस्या पैदा हो रही है
मैं Tensorlake का founder हूँ
हमने developers के लिए document parsing API बनाया है
PDF parsing में Computer Vision approach असल दुनिया में काम क्यों करती है, इसकी वजह यही है
file के अंदर के metadata पर ही निर्भर रहना, PDF के अलग-अलग sources के साथ scale नहीं करता
इसलिए हम PDF को image में बदलते हैं, फिर पहले layout recognition model चलाते हैं, उसके बाद text और table recognition जैसे specialized models चलाते हैं, और फिर उन टुकड़ों को जोड़ते हैं, ताकि उन domains में भी उपयोगी नतीजे मिलें जहाँ accuracy बहुत ज़रूरी है
ऊपर-ऊपर से यह तरीका थोड़ा हास्यास्पद लगता है, लेकिन असल में शायद यही सबसे practical solution है
PDF मूल रूप से इंसानों के पढ़ने लायक layout दिखाने के लिए बना फ़ॉर्मेट है; यह कंप्यूटर द्वारा पढ़े जाने के लिए design नहीं किया गया, बल्कि अच्छे visual display पर केंद्रित है
इसलिए इंसानों की पढ़ने की प्रक्रिया की नकल करने वाला approach तर्कसंगत लगता है
फिर भी यह अफ़सोस की बात है कि 30 साल से ज़्यादा समय में PDF machine readability को बेहतर नहीं बना पाया
सोचता हूँ कि कौन-सा incentive नहीं था, जिसकी वजह से यह संभव नहीं हो सका
अगर किसी के पास इस बारे में insight हो, तो सुनना चाहूँगा
इसमें थोड़ा व्यंग्य है
PDF को print करके scan करना और फिर email करना आम तौर पर मज़ाक का विषय लगता है, लेकिन PDF parsing में हम असल में लगभग वही काम कर रहे होते हैं
यह काफ़ी झुंझलाहट भरी हक़ीक़त है कि ऐसा approach ज़रूरी पड़ता है
दुनिया HTML को ऐसे parse नहीं करती
मैं Nutrient.io का co-founder हूँ, और 10 साल से ज़्यादा समय से PDF पर काम कर रहा हूँ
web browser की तरह PDF viewers को भी बेहद विविध तरह के PDF स्वीकार करने पड़ते हैं
PDF इतना पुराना फ़ॉर्मेट है कि file generators अक्सर मनमाने बदलाव कर देते हैं, बस उनके अपने viewer में सही दिखना चाहिए
इसलिए हमारी company ने AI document processing SDK बनाया है, जो REST API के ज़रिए PDF इनपुट लेकर JSON में structured data लौटाता है
visual methods के साथ-साथ structural pre-processing और post-processing के अनुभव की वजह से, हमें pure vision-based approaches की तुलना में performance और cost दोनों में बेहतर नतीजे मिलते हैं
अगर आप खुद PDF processing की झंझट में नहीं पड़ना चाहते और अपने core work पर ध्यान देना चाहते हैं, तो यह मददगार हो सकता है
https://www.nutrient.io/sdk/ai-document-processing
चूँकि यहाँ PDF internals के expert मौजूद हैं, एक सवाल है
यह जानना चाहता हूँ कि mupdf-gl, कम-से-कम default desktop Linux पर, बाकी सभी programs से इतना ज़्यादा तेज़ क्यों है
बड़े PDF में search की इसकी speed साफ़ तौर पर बहुत बेहतर है; मैं हमेशा सोचता रहा हूँ कि दूसरे viewers इतने तेज़ क्यों नहीं हो पाते
अगर किसी के पास इस पर insight हो, तो सुनना चाहूँगा
आख़िरकार आपने parsing का काम उस software को outsource कर दिया जो PDF को image में render करता है
मैं बहुत समय से सोचता आया हूँ कि हमें layout-केंद्रित document communication से आगे बढ़ना चाहिए
यानी, professionally polished layout अपने-आप में असल में एक पुरानी परंपरा जैसा है, और content की वास्तविक समझ से उसका बहुत कम संबंध है
उदाहरण के लिए, regulatory filings अक्सर बेहद मोटे documents होते हैं, और layout rules मिलाने के लिए Microsoft Word में बहुत समय लग जाता है
layout guarantee करने के लिए इन्हें DOCX या PDF में जमा किया जाता है, लेकिन ये formats programs द्वारा अपने-आप content extract या transform करने के लिए बहुत अनुपयुक्त हैं
LLM इन files को पढ़ सकता है, लेकिन साधारण machine-friendly files, जैसे text, markdown, XML, JSON, की तुलना में इसका compute cost बहुत ज़्यादा होता है
एक विकल्प के रूप में मैंने सोचा है कि पूरी तरह 'machine-first' और 'content-first' simple formats, जैसे JSON, XML, या HTML-आधारित standards, को standardize किया जाए
इनमें सिर्फ़ न्यूनतम structure और image embedding की जानकारी हो, और इंसान जब पढ़ें तो viewer app उसे सुंदर तरीके से reconstruct कर दे
machine processing बहुत आसान हो जाएगी
HTML/browser, EPUB जैसे मिलते-जुलते formats पहले से मौजूद होने के बावजूद, मुझे लगता है कि पुराने तरीक़े को बदलने का समय आ गया है
उम्मीद है कि LLM revolution हमें इस दिशा में ले जाएगा, और आगे चलकर महँगी PDF parsing सिर्फ़ legacy pipeline बनकर रह जाएगी
मैंने अभी तक DOCX parser नहीं बनाया, लेकिन DOCX XML-based है, और जब तक explicitly layout specify न किया जाए तब तक सब कुछ absolute coordinates में नहीं बदलता; तो अगर JPEG को 0 अंक, PDF को 15 अंक, और markdown को 100 अंक दें, तो शायद DOCX लगभग 80 अंक जितना आसान होगा
मुझे लगा यह बहुत बढ़िया summary थी, और एक अतिरिक्त point भी दिलचस्प लगा
Incremental-save chain: पहला startxref offset तो ठीक होता है, लेकिन Acrobat जब कई बार edits जोड़ता है, तो बार-बार append किए गए /Prev links अक्सर अगले xref की ओर कुछ bytes कम दिखाते हैं
ज़्यादातर viewers, जिनमें PDF.js, MuPDF, और Adobe Reader भी शामिल हैं, obj token को पूरी file में brute-force ढूँढकर नई table reconstruct कर लेते हैं, जबकि spec-friendly parser फट जाता है
अगर आप field में कई applications द्वारा बार-बार modified documents को संभालना चाहते हैं, तो ऐसे salvage path ज़रूरी हैं
कई बार पुराना reference, या chain में कोई reference, file के बाहर के offset, 0 offset, या किसी ग़लत value की ओर इशारा करता है
यह लिखने की मेरी प्रेरणा मेरे project PdfPig के शुरुआती parsing logic को फिर से बनाने से आई
शुरू में मैंने Java PDFBox code को port किया था, लेकिन मैं इसे और तेज़ और सरल बनाना चाहता था
नया logic अगर एक भी xref table/stream मिस कर दे, तो पूरी file scan करता है, और recovery path में सिर्फ़ उसी offset पर भरोसा करता है
लेकिन यह पहले से साफ़ तौर पर धीमा हो गया है, और यह बदलाव सच में ठीक है या नहीं, इस पर भरोसा करना मुश्किल है
मैं 10,000 files के test set के साथ अलग-अलग edge cases खोज रहा हूँ
https://github.com/UglyToad/PdfPig/pull/1102
अगर सब कुछ अच्छी assumptions और एक सही PDF object parser के साथ हो, तो यह आसान लग सकता है, लेकिन असलियत में ऐसा बिल्कुल नहीं है
यह पूरी स्थिति PDF नरक जैसी है
PDF कोई specification नहीं, बल्कि एक social contract, एक तरह का 'vibe' है
जितना ज़्यादा इससे जूझते हैं, उतना ही गहरे धँसते जाते हैं, और अब लगता है कि हम सब ईश्वर की नज़र से दूर किसी दलदल में रह रहे हैं
इस बात पर मैं हँस पड़ा
"क्या आप PDF parse करना चाहते हैं" इस सवाल पर मैं पूरी निश्चितता से कह सकता हूँ: बिल्कुल नहीं
वजह मूल पोस्ट में बहुत अच्छी तरह समझाई गई है
काश मेरा bank चीज़ें किसी ज़्यादा readable format में देता, लेकिन तब तक मेरे पास कोई विकल्प नहीं है
मैं यह ग़लती पहले कर चुका हूँ, और दोबारा कभी नहीं करना चाहता
PDF parser लिखने के अनुभव वाले व्यक्ति के रूप में मुझे PDF सचमुच बहुत अजीब फ़ॉर्मेट लगता है
शायद binary और text के मिश्रण के रूप में इसकी मूल design ने ही इसे इतना विचित्र बनाया है
थोड़े-बहुत ग़लत xref offsets वाली समस्या भी शायद LF/CR newline conversion handling के bug से आई होगी
लेख में जिन बातों का ज़िक्र नहीं था, उनमें एक यह है कि modern PDF, यानी v1.5+, में अक्सर plain-text xref tables नहीं होतीं, बल्कि "xref stream" होता है
v1.6 और उसके बाद object खुद भी object stream के अंदर हो सकते हैं
सब कुछ ठीक लगता है, लेकिन फिर पता चलता है कि जिस object की ज़रूरत है वह किसी stream के अंदर है, वह stream ख़ुद PNG compression के modified version का इस्तेमाल कर रही है, या offsets flate-compressed xref stream के अंदर हैं, तब मामला मुश्किल हो जाता है
ऊपर से कई document versions आपस में mixed होते हैं, इसलिए यह तय करना भी जटिल हो जाता है कि नवीनतम हिस्सा कहाँ से कहाँ तक है
PDF 1.7 तक के documents आसानी से मिल जाते हैं, लेकिन सिर्फ़ दो साल पहले तक PDF 2.0 specification paywall के पीछे थी
PDF ऐसा फ़ॉर्मेट है जिसे streaming ध्यान में रखकर नहीं बनाया गया
आखिर में मौजूद trailer dictionary की वजह से पूरी file load हुए बिना parsing मुश्किल हो जाती है
हालाँकि, "streamable PDF" जैसी चीज़ भी होती है, जहाँ शुरुआती हिस्से में ज़रूरी जानकारी हो तो पहली page को तुरंत render किया जा सकता है, भले बाकी नहीं
वैसे, हाल के समय में मेरा PDF क्षेत्र से थोड़ा कम संपर्क रहा है, इसे ध्यान में रखें
footer होने के बावजूद, अगर website Range Request support करे और Content-Length header सही ढंग से दे, तो PDF की streaming संभव है
streaming reader पहले HEAD request करेगा, फिर file के आख़िरी कुछ सौ bytes मंगाकर pointer और table निकालेगा, और उसके बाद बाक़ी हिस्सा लेगा
यह live-generated PDFs के लिए उपयुक्त नहीं है, लेकिन काफ़ी पुराने web servers पर भी सिर्फ़ 1-2 अतिरिक्त round trips काफ़ी होते हैं
अफ़सोस है कि file-by-file Range-based parser पर कम ध्यान दिया जाता है, लेकिन तकनीकी रूप से यह असंभव नहीं है
सही है, Linearized PDF नाम का एक format होता है, जिसे इस तरह बनाया गया है कि पहली page पूरी file download किए बिना जल्दी दिखाई जा सके
summary में उसे इसलिए छोड़ा गया था क्योंकि उसके लिए काफ़ी अतिरिक्त explanation चाहिए होती
Python सीखते समय जिन शुरुआती projects पर मैंने हाथ लगाया था, उनमें से एक PDF parser भी था
मेरा लक्ष्य DnD campaign के लिए maps को अपने-आप extract करना था, लेकिन नतीजा असफल रहा (हँसी)
मैंने एक बार TIFF reader लिखा था
TIFF भी ऐसा फ़ॉर्मेट है जो लिखने में आसान लेकिन पढ़ने में बेहद कठिन होने के लिए बदनाम है
PDF भी मुझे उसी श्रेणी का लगता है