2 คะแนน โดย GN⁺ 2025-02-11 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • PDFSyntax เป็นไลบรารี Python ที่เน้นไปที่บทที่ 7 “Syntax” ของข้อกำหนด PDF ใช้สำหรับตรวจสอบและแปลงโครงสร้างเอกสารภายในของไฟล์ PDF ได้ละเอียดถึงระดับไบต์
  • เขียนขึ้นใหม่ทั้งหมดด้วย Python ล้วน และเป็นไลบรารีขนาดเล็กที่ไม่มี dependency โดยให้ความสำคัญกับความเรียบง่ายและความไม่เปลี่ยนแปลงของข้อมูล
  • วิธีแก้ไขพื้นฐานคือการใช้ incremental update แบบไม่ทำลายข้อมูลเดิม ตามที่ข้อกำหนด PDF อนุญาต โดยจะเพิ่มส่วนการเปลี่ยนแปลงไว้ท้ายไฟล์ต้นฉบับ และสามารถย้อน revision หรือรวมให้เป็น revision เดียวได้
  • CLI มีคำสั่ง overview, disasm, text, fonts, browse เป็นต้น โดย browse จะจัดรูปแบบซอร์ส PDF ให้อ่านง่าย และเปิดให้สำรวจโครงสร้างภายในผ่าน HTML แบบสแตติก ที่มีไฮเปอร์ลิงก์
  • ปัจจุบันยังเป็นโปรเจ็กต์ระหว่างพัฒนาที่มีคุณภาพระดับ เบตา โดย API อาจเปลี่ยนแปลงได้ตลอดเวลา และแม้จะใช้ไลเซนส์ MIT แต่ยังไม่รับ contribution จากภายนอก

การตรวจสอบและแปลงโครงสร้างภายในของ PDF

  • PDFSyntax เป็นไลบรารี Python สำหรับตรวจสอบและแปลงโครงสร้างภายในของไฟล์ PDF
  • มุ่งเน้นไปที่บทที่ 7 “Syntax” ของ Portable Document Format (PDF) Specification
  • มีการจัดการโครงสร้างเอกสารในระดับไบต์ ทำให้ใช้งานได้ในกรณีต่อไปนี้
    • เข้าถึง metadata
    • หมุนหน้าเอกสาร
    • งานอ่าน/เขียน PDF
    • เข้าถึงและจัดการอ็อบเจ็กต์ภายใน

แนวทางการออกแบบ

  • ฟังก์ชันภายในถูกเปิดให้ใช้งานเป็น API toolkit สำหรับงานอ่าน/เขียน PDF
  • บางความสามารถมีให้ใช้ผ่าน CLI เพื่อใช้งานในเทอร์มินัลหรือเบราว์เซอร์
  • ไลบรารีนี้เขียนด้วย Python ล้วนและไม่มี dependency ภายนอก
  • ให้ความสำคัญกับความเรียบง่ายและimmutability
  • วิธีแก้ไขเริ่มต้นคือ incremental update ที่ไม่เขียนทับไฟล์ต้นฉบับโดยตรง แต่เพิ่มส่วนที่เปลี่ยนแปลงไว้ท้ายไฟล์ต้นฉบับ
    • หากจำเป็นสามารถย้อน revision ได้
    • หรือจะรวมทุก revision ให้เป็นหนึ่งเดียวก็ได้

การติดตั้งและการใช้งาน CLI

  • ติดตั้งได้จาก PyPI
pip install pdfsyntax
  • รูปแบบการใช้งานพื้นฐานของ CLI คือ
pdfsyntax COMMAND FILE
  • หากติดตั้งจากซอร์ส สามารถรันด้วยรูปแบบที่ยาวกว่าได้
python3 -m pdfsyntax COMMAND FILE
  • คำสั่งหลักสำหรับวิเคราะห์ PDF อย่างรวดเร็วมีดังนี้
    • overview: แสดงข้อมูลข้อความเกี่ยวกับโครงสร้างและ metadata
    • disasm: แสดงดัมพ์โครงสร้างไฟล์ในเทอร์มินัล
    • text: แสดงข้อความที่สกัดออกมาโดยคงการจัดวางเชิงพื้นที่แบบเอกสารสแกน
    • fonts: แสดงรายการฟอนต์ที่ใช้งาน
    • browse: จัดรูปแบบซอร์ส PDF ให้อ่านง่าย และสร้าง HTML แบบสแตติก พร้อมไฮเปอร์ลิงก์เพื่อช่วยสำรวจโครงสร้างภายใน

วิธีใช้งาน API

  • PDFSyntax ประกอบด้วยฟังก์ชันเรียบง่ายเป็นส่วนใหญ่
  • สามารถอ่าน PDF ด้วย readfile และดึง metadata ในรูปแบบ Python dict ได้ด้วย metadata
>>> from pdfsyntax import readfile, metadata
>>> doc = readfile("samples/simple_text_string.pdf")
>>> metadata(doc)
  • อ็อบเจ็กต์ Doc เป็นคลาสเฉพาะทางแทบจะเพียงคลาสเดียวที่ใช้เก็บสถานะภายในของเอกสาร
    • เนื้อหาที่ถูกแคชหรือ memoize จากไฟล์ต้นฉบับ
    • การเปลี่ยนแปลงจากการเพิ่ม·แก้ไข·ลบเนื้อหา
    • ประวัติการแก้ไขที่ติดตามผ่าน incremental update
  • ฟังก์ชัน metadata เดียวกันนี้ก็สามารถใช้เป็นเมธอดของอ็อบเจ็กต์ Doc ได้เช่นกัน
>>> doc.metadata()
  • สามารถเข้าถึงและจัดการอ็อบเจ็กต์ภายในเอกสารได้โดยตรงผ่านฟังก์ชันระดับล่างอย่าง get_object, update_object
  • และยังมีฟังก์ชันระดับสูงอย่าง rotate ให้ใช้งานด้วย
>>> from pdfsyntax import rotate, writefile
>>> doc180 = rotate(doc, 180)
  • ในตัวอย่างการหมุน อ็อบเจ็กต์ต้นฉบับจะไม่ถูกเปลี่ยนแปลง และจะมีการสร้างอ็อบเจ็กต์ใหม่ที่เก็บการเปลี่ยนทิศทางที่กำลังดำเนินอยู่
  • สามารถเขียน PDF ที่แก้ไขแล้วลงดิสก์ได้ด้วย writefile
>>> writefile(doc180, "rotated_doc.pdf")
  • ไฟล์ผลลัพธ์จะอยู่ในรูปแบบที่มีการเพิ่มเซกชันใหม่ต่อท้ายเนื้อหาต้นฉบับ และสามารถย้อนการเปลี่ยนแปลงได้ด้วยการตัดเซกชันนี้ออก

สถานะปัจจุบันและนโยบายการรับ contribution

  • โปรเจ็กต์นี้ยังอยู่ ระหว่างพัฒนา และเป็นซอฟต์แวร์คุณภาพระดับเบตา
  • API อาจเปลี่ยนแปลงได้ทุกเมื่อ
  • รายการงานถัดไปมีหัวข้อต่อไปนี้รวมอยู่ด้วย
    • การตัดและต่อหน้าเอกสาร
    • การบีบอัดแบบไม่สูญเสียข้อมูล
    • ฟิลเตอร์เพิ่มเติม
    • การปรับปรุงการสกัดข้อความ
    • การเสริมการสกัดข้อความด้วยการตรวจจับเลย์เอาต์
  • PDFSyntax ใช้ ไลเซนส์ MIT
  • ปัจจุบันยังไม่รับ contribution จากภายนอก
    • เป็นโปรเจ็กต์ส่วนตัวและมีเวลาจำกัด
    • มีแผนจะมุ่งเน้นที่ฟีเจอร์ใหม่และ roadmap การรีแฟกเตอร์ก่อน แล้วจึงค่อยเปิดรับ contribution เมื่อระบบนิ่งขึ้น

1 ความคิดเห็น

 
GN⁺ 2025-02-11
ความคิดเห็นบน Hacker News
  • นานมาแล้วเคยได้รับงานให้ดึงข้อมูลจาก PDF หลายไฟล์ และทำเครื่องมือสำหรับแสดงภาพการจัดวางตัวอักษรบนหน้า รวมถึงกรอบขอบเขตของทุกองค์ประกอบ
    สุดท้ายโปรเจกต์ล้มเหลวโดยสิ้นเชิง และมีบางคนไม่พอใจเพราะไม่ได้ผลลัพธ์ตามที่คาด
    ถ้าเป็นตอนนี้ ผมคงหันไปใช้ ความสามารถของ LLM ในการดึงข้อมูลจาก PDF แบบ 100% แน่นอน ตอนนั้นยังไม่มีตัวเลือกแบบนั้น

    • การพาร์สข้อมูลจาก PDF ใดๆ แทบจะเป็น ภารกิจต้องสาป PDF ใส่รูปภาพได้ด้วย ดังนั้นมันจึงคล้ายกับการจัดการ JPEG โดยตรงเสียมากกว่า
      ถ้าตั้งความคาดหวังให้เหมาะ OCR ก็พาไปได้ไกลพอสมควร แต่จากประสบการณ์ของผม มันมักจะขาดอีกนิดจากสิ่งที่ต้องการพอดีเสมอ
    • LLM อาจช่วยจัดลำดับตัวอักษรที่ดึงออกมาจากหน้าได้ แต่การได้เนื้อหาจริงๆ ออกมายังคงยากอยู่
      กรณีที่เห็นมาหลายครั้งคือ ตัวอักษรในข้อความเป็น glyph ของฟอนต์แบบกำหนดเอง ที่ไม่มีแมปปิงแบบ ASCII หรือเป็นตัวอักษรที่วาดขึ้นจากเส้น ซึ่งพบบ่อยเป็นพิเศษในงานส่งออกจาก CAD
      แบบนั้นจะไม่มีข้อความที่ระบุตัวตนได้ให้ดึงออกมา สุดท้ายก็ต้องกลับไปตรวจหน้าเอกสารด้วย OCR อีกครั้ง
    • ที่ทำงานเก่าผมเคยเจอเรื่องคล้ายกัน วิธีพาร์สแบบอิงกฎทำให้ดีจริงๆ ได้ยากมาก และมักพังกับ edge case
      พวกเรากำลังสร้าง pipeline ประมวลผล PDF ตั้งแต่ต้นบนพื้นฐานของ LLM และโมเดลภาษา-ภาพที่ https://runtrellis.com/ และเห็นความแม่นยำใกล้ 100% แม้กับ PDF ที่จัดการยาก
      หัวใจคือการใช้เอนจินแบบอิงกฎร่วมกับข้อมูลอ้างอิงเพื่อตรวจสอบผลลัพธ์ข้ามกัน
    • นานมาแล้วเคยทำงานดึง แบบร่าง 2D CAD จาก PDF แล้วแปลงเป็น 3D เต็มรูปแบบ สนุกพอสมควรเลย
    • pdfjs ทำงานพวกนั้นให้ทั้งหมดและค่อนข้างทนทาน ช่วงหลังผมใช้มันดึงข้อมูลตารางจากรายการเดินบัญชีธนาคารย้อนหลัง 10 ปี
  • เท่มาก ถ้าที่ทำงานเก่ามีสิ่งนี้ ผมน่าจะใช้เยอะเลย
    ในอุดมคติ อยากให้เป็นแบบ https://lapo.it/asn1js/ คือโยนไฟล์เข้าไปแล้วประมวลผลทุกอย่าง ในเครื่อง

  • ด้วย “สิทธิพิเศษ” ที่ได้ดูแลโค้ดสำหรับดึงข้อมูลจาก PDF ผมจึงใช้ iText RUPS เวอร์ชันฟรีเพื่อดีบัก PDF มาพักหนึ่งแล้ว
    ฟีเจอร์ตรวจสอบภายในของที่นี่ดูทรงพลังกว่า น่าจะดีมาก ตั้งใจว่าจะลองรันดู

  • จำได้ว่าเคยมีโปรเจกต์คล้ายๆ กันบน GitHub สามารถแสดงภาพ ข้อมูลไบนารี ใดๆ ตามสคีมาที่กำหนดได้ และเหมือนจะมีตัวอย่าง TCP/IP ด้วย

    • อาจจะเป็น https://kaitai.io/ หรือเปล่า?
      ดูเหมาะกับบทบาทนั้นมาก แต่โปรเจกต์ล่าสุดของผมต้องการ serialization ด้วย เลยไม่ได้ใช้
    • HexFiend ก็มีไวยากรณ์เทมเพลตสำหรับแสดงภาพข้อมูลไบนารีเช่นกัน อิง Tcl
      https://github.com/HexFiend/HexFiend/blob/master/templates/T...
    • ในบริบทนี้ คำว่า “ใดๆ” ต้องระวังหน่อย
      น่าสนใจที่เวลาผมทดสอบตัวบรรยายรูปแบบไฟล์แบบนั้น ผมใช้ PDF เป็น “Hello World” เพราะสเปก PDF ประหลาดมาก
      ถ้าภาษาเชิงเทคนิคสามารถอธิบายเลย์เอาต์ของ PDF ได้อย่างถูกต้อง ก็ถือได้ว่าออกแบบมาดีแน่นอน
      จนถึงตอนนี้ยังไม่ค่อยโชคดีนัก ยกเว้นพวกที่ออกจากโหมดประกาศได้แล้วสั่งว่า “จากนั้นให้รันโค้ดนี้”
  • อันนี้น่าจะสะดวกสำหรับ งานนิติวิทยาศาสตร์ดิจิทัล และการหา watermark ด้วย

    • ดูน่าสนใจ ผมไม่ค่อยรู้เรื่องนี้ อยากทราบว่าเอาไปใช้ ตรวจจับ watermark ได้อย่างไร? ใช้วิธีเดียวกันตรวจจับลายเซ็นได้ไหม?
  • ดูดี
    ถ้าแสดงทุก byte ของ PDF ได้จะดีขึ้นอีก ดูเหมือน endobj กับ xref จะไม่แสดง

    • ใช่ เดี๋ยวจะแก้เร็วๆ นี้
  • ถ้าออกมาเป็น ไลบรารีบนเบราว์เซอร์ คงดีมาก แค่ลากไฟล์มาวางแล้วดูข้างในได้ ถึงอย่างนั้นก็น่าประทับใจอยู่ดี

    • หมายถึงส่วนขยายเบราว์เซอร์หรือเปล่า? ไม่ได้จะเสียมารยาทนะ แค่อยากเช็กว่าผมเข้าใจถูกไหม
  • ทำได้ดีมาก เป็น เครื่องมือพรีวิวด้านความปลอดภัย ที่มีประโยชน์มาก PDF นี่ตัวปัญหาเลย

  • สงสัยว่าเครื่องมือ UI ที่ใช้แสดงภาพเป็นไลบรารีหรือเปล่า
    ชอบรูปแบบ UI มาก อยากเอาไปใช้แยกส่วนและดีบัก byte stream ของวิดีโอด้วย
    แก้ไข: จริงๆ แล้วค่อนข้างเรียบง่าย ใช้ CSS ได้ดี! https://github.com/desgeeko/pdfsyntax/blob/main/docs/simple_...

    • ใช่แล้ว ผมให้ความสำคัญกับความเรียบง่าย และ interaction ที่ HTML กับ CSS พื้นฐานมีให้ก็เพียงพอสำหรับ use case ของผม :)
  • ในทำนองเดียวกัน ทำไม PDF ถึงยังไม่ถูกแทนที่นะ? มี XPS, DjVu, XHTML(EPUB) แต่ทั้งหมดดูเหมือนเล็ง use case ต่างกัน เช่นไปทางไฟล์ HTML ที่แพ็กเกจไว้
    สิ่งที่ผมอยากได้คือ รูปแบบเอกสารที่เรียบง่าย ซึ่งฝังไฟล์อื่นและ metadata ได้ โดยไม่มีความเทอะทะของ Adobe
    ต้องใส่ hyperlink ภายในหน้าได้ เปลี่ยนขนาดตัวอักษรแล้วข้อความไม่ล้น และพิมพ์ออกมาได้อย่างสม่ำเสมอ

    • ผมไม่คิดว่าเหตุผลที่ PDF กลายเป็นรูปแบบที่ “ไม่เหมาะ” สำหรับการแก้ไข การอ่านบนอุปกรณ์ และการดึงข้อมูลเชิงความหมายแทนข้อมูลเชิงการนำเสนอ จะเป็นความผิดของ Adobe หรือความเทอะทะ
      PDF ไม่ใช่รูปแบบข้อมูล แต่เป็น รูปแบบบรรยายหน้าเอกสาร ดังนั้นทุกการตัดสินใจจึงมาจากความจำเป็นที่จะทำให้พิมพ์ “หน้า” เดียวกันได้ แม้ใช้ระบบปฏิบัติการ ซอฟต์แวร์ เครื่องพิมพ์ และขนาดกระดาษจริงที่ต่างกัน
      เหตุผลหลักที่ PDF อยู่ได้นานน่าจะเป็นเพราะหลายสิ่งยังทำงานบน paradigm ของเอกสาร กล่าวคือมอง “เอกสาร” เป็น “มัดกระดาษหลายแผ่น”
      ตั้งแต่สรุปหลังพบแพทย์ในโรงพยาบาลไปจนถึงเอกสารทะเบียนรถ ล้วนมีการนำเสนอทางสายตาเฉพาะที่ถูกเลือกมาแล้วให้ดูเหมาะสมและพอดีเป๊ะบนกระดาษ
      HTML เช่นรูปแบบที่ทำให้รันได้ในตัวเองด้วยการใส่รูปภาพและ CSS เป็น data URL หรือ ePub อาจดีกว่าในแทบทุกด้าน
      แต่เป้าหมายต่างกันเกินไป ถ้าวันนี้ไปชวนคนที่สร้าง PDF ให้เปลี่ยนไปใช้แบบนั้น คุณคงได้ยินข้อร้องเรียนว่าแต่ละอุปกรณ์แสดงเนื้อหาไม่เหมือนกันเล็กน้อย และการแบ่งหน้าก็ยังเปลี่ยนไปตามการตั้งค่าได้
      เรื่องที่เกี่ยวข้องและน่าสนใจคือ แม้แต่ Google Docs ซึ่งเอกสารน่าจะถูกพิมพ์หรือแปลงเป็น PDF น้อยกว่าครึ่งมากๆ ค่าเริ่มต้นก็ยังเป็น โหมดหน้า ไม่ใช่โหมด “ไม่มีหน้า”
      โหมด “ไม่มีหน้า” มีประโยชน์กว่ามาก เพราะเหมือนหน้าเว็บทั่วไป คือปรับตามหน้าต่างและเลื่อนบนพื้นผิวต่อเนื่องเดียวไปได้เรื่อยๆ
    • use case ต่างกัน
      ข้อกำหนดว่า “ไม่ให้ข้อความล้น” มีรายละเอียดตามมามากมาย
      ใน PDF ทุกตัวอักษร อักขระ และ glyph ของข้อความสามารถมีตำแหน่ง x,y ที่แน่นอนบนหน้า หรือบางครั้งอยู่นอกหน้าก็ได้
      จึงสามารถ จัดวางเนื้อหาอย่างแม่นยำ ได้ไม่ว่ารอบๆ จะมีอะไร แอปพลิเคชันที่ใช้ PDF ต้องวางรายการให้ถูกต้อง และต้อง implement การตัดบรรทัดตามตัวอักษรหรือคำเอง
      XPS เคยใกล้ที่สุดกับการนำ PDF มาทำใหม่ แต่ Microsoft ไม่สามารถได้รับแรงสนับสนุนเพียงพอจากฝ่ายอื่นๆ จึงค่อยๆ เลือนหายไป
    • สิ่งที่น่าสนใจเกี่ยวกับ PDF ซึ่งผมเพิ่งรู้ไม่นานมานี้คือ PDF เป็น subset ของ PostScript และนั่นเป็นสาเหตุหนึ่งที่ทำให้มันหนักอยู่บ้าง
      PostScript แม้จะแปลก แต่เป็นภาษาโปรแกรมมิงเต็มรูปแบบ ส่วน PDF ไม่ใช่ กล่าวคือไม่ใช่ Turing complete
      PDF ไม่รองรับ control flow ดังนั้นสิ่งที่ใน PostScript เขียนเป็นลูปง่ายๆ ได้ ใน PDF ต้องคลี่ออกแล้วเก็บเป็นชุดของ declaration หรือ expression ง่ายๆ
      ข้อดีคือการ render PDF ไม่จำเป็นต้องมี interpreter ของโปรแกรมเต็มรูปแบบ
    • พอบทสนทนาแบบนี้เริ่มขึ้น ฝ่าย LaTeX ก็จะโผล่มา แล้วทุกคนที่อาจเติมอะไรที่มีความหมายให้มาตรฐานได้ก็จะติดอยู่กับการถกเถียงนั้น
    • เหตุผลหนึ่งคือไม่มีรูปแบบอื่นใดที่เหมาะกับ งานพิมพ์เชิงพาณิชย์ ได้โดยตรง