รีวิว MarkItDown: ตัวแปลงไฟล์เป็น Markdown ที่ไม่ใช่สแครปเปอร์

อัปเดตล่าสุดเมื่อ July 17, 2026
รีวิว MarkItDown: ตัวแปลงไฟล์เป็น Markdown ที่ไม่ใช่สแครปเปอร์
สรุปด้วย AI
รีวิว MarkItDown ชิ้นนี้อธิบายให้ชัดว่าเครื่องมือของ Microsoft เป็นตัวแปลงไฟล์เป็น Markdown ไม่ใช่ตัว crawler หรือระบบทำเว็บอัตโนมัติ บทความทดสอบอินพุตจริงอย่าง PDF, DOCX, XLSX และ PPTX แล้ววัดทั้ง footprint ของแพ็กเกจ เวลาเริ่มต้นใช้งาน ความแม่นยำของตาราง เวลารันตามขนาดเอกสาร และการใช้หน่วยความจำของสเปรดชีต ผลที่ได้คือ MarkItDown ใช้งานได้เร็วและดีมากกับอินพุตที่สะอาด แต่มีภาระ dependency ด้าน machine learning ที่เกินคาด และสามารถเก็บข้อความในตารางไว้ได้แม้โครงสร้างคอลัมน์จะเสียแบบเงียบ ๆ บทความนี้เหมาะกับทีมที่ต้องแปลงเอกสารเป็น Markdown เพื่อใช้กับ search, RAG หรือ workflow ความรู้ภายในองค์กร

MarkItDown มักถูกเอาไปวางรวมกับเว็บสแครปเปอร์อยู่บ่อย ๆ แต่จริง ๆ แล้วมันไม่ใช่แบบนั้นเลย เครื่องมือนี้ไม่มีตัว crawler, ไม่มีเอนจิน JavaScript และไม่มีวิธีดึง URL มาแล้วล้างโค้ดส่วนเกินออก สิ่งที่มันทำคือรับไฟล์ที่คุณมีอยู่แล้ว — ไม่ว่าจะเป็น PDF, เอกสาร Word, สเปรดชีต, หรือสไลด์ — แล้วแปลงทั้งหมดให้เป็น Markdown ที่โมเดลภาษาอ่านได้

ผมใช้เวลาสองสามสัปดาห์ทดสอบ Microsoft MarkItDown กับเอกสารจริงหลากหลายชุดบน Mac เครื่องเดียว โดยให้คะแนนทุกตารางเทียบกับ manifest ที่ผมเตรียมไว้ก่อนเริ่มรัน และจับเวลาทุกการแปลง สรุปสั้น ๆ คือ: ถ้าเป็นอินพุตที่สะอาด มันทั้งเร็วและแม่นยำ แต่แพ็กเกจของมันแอบพ่วง runtime ด้าน machine learning ขนาด 73 MB ที่คุณอาจไม่ได้ต้องการ และตารางบางแบบก็พังในลักษณะที่อาจผ่านด่าน "ข้อความยังอยู่ครบไหม" แต่ไม่ผ่านด่าน "ข้อมูลอยู่คอลัมน์ถูกหรือเปล่า" นี่คือภาพรวมทั้งหมดพร้อมตัวเลข

จริง ๆ แล้ว MarkItDown คืออะไร

MarkItDown เป็นยูทิลิตี้ภาษา Python จาก Microsoft สำหรับแปลงไฟล์และเอกสาร Office ให้เป็น Markdown ที่เหมาะกับการใช้งานกับ LLM แค่ชี้ไปที่ PDF, .docx, .xlsx, .pptx, รูปภาพ, ไฟล์ HTML หรือฟอร์แมตอื่น ๆ อีกหลายแบบ มันก็ส่ง Markdown กลับมาให้ เครื่องมือนี้เรียกใช้ได้ 3 ทาง: ผ่าน CLI (markitdown file.pdf -o out.md หรือรับข้อมูลจาก stdin), ผ่าน Python API (MarkItDown().convert(...)), และผ่าน MCP server แบบเลือกติดตั้งสำหรับเวิร์กโฟลว์ของเอเจนต์

MarkItDown converts existing files to Markdown and is not a crawler

สิ่งสำคัญที่สุดคือสิ่งที่มัน ไม่ได้ ทำ เพราะ README ก็ไม่ได้อ้างว่าทำ และผมยืนยันจากการทดสอบแล้ว: ไม่มี crawling, ไม่มี rendering JavaScript, ไม่มีการไล่ลิงก์, ไม่มีการไล่หน้าถัดไป และไม่มีการดึงเฉพาะเนื้อหาหลักแบบเดียวกับเครื่องมืออ่านบทความ มันคือ converter สำหรับทั้งเอกสาร คุณเอา bytes มาให้ มันก็แปลงให้เป็นมาตรฐาน ความต่างเล็ก ๆ นี้แหละเป็นตัวตัดสินเลยว่าเครื่องมือนี้ควรอยู่ในสแต็กของคุณหรือไม่ ผมเลยจะย้ำประเด็นนี้กลับมาอีกหลายครั้ง

ตัว repo เองถือว่าใหญ่ตามตัวเลขสวย ๆ ของ GitHub — 165,282 stars และ 11,790 forks ณ กลางเดือนกรกฎาคม 2026 ใช้สัญญาอนุญาต MIT และเวอร์ชันล่าสุด (v0.1.6) ออกเมื่อ 2026-05-26 แต่ดาวจำนวนมากไม่ได้แปลว่า internals ของตัวแปลงจะสุกงอมเสมอไป มันเป็น repo ของ Microsoft ที่ได้แรงหนุนจากกระแสเครื่องมือสำหรับ LLM มากกว่า และยังมี issue เปิดอยู่อีก 833 รายการ โดยบางอันเกี่ยวโดยตรงกับสิ่งที่คุณควรรู้ก่อนติดตั้ง

HTML เป็น Markdown: เร็ว ครบ แต่โค้ดส่วนเกินติดมาด้วย

เพราะซีรีส์รีวิวสแครปเปอร์ของผมใช้เว็บฟิกซ์เจอร์ชุดเดียวกัน 4 หน้า ผมจึงป้อน MarkItDown ด้วยไฟล์ HTML ท้องถิ่นชุดเดียวกัน ไม่ใช่เพื่อให้คะแนนในฐานะสแครปเปอร์ แต่เพื่อดูว่ามันแปลง HTML เป็น Markdown ได้ดีแค่ไหน ซึ่งในหน้าที่ติดแท็กมาดี มันทำได้ดีจริง

ทั้ง 4 หน้าถูกแปลงได้ด้วยการติดตั้งหลักโดยไม่ต้องลงส่วนเสริมเพิ่ม และ probe ทุกตัวที่ผูกไว้กับเนื้อหาหลักยังอยู่ครบ หน้า Wikipedia "Web scraping" article (226 KB) ออกมาพร้อมโครงสร้างหัวข้อที่สะท้อนต้นฉบับได้ตรง — h1 หนึ่งตัว, h2 เจ็ดตัว, h3 สิบสองตัว ตามโครงสร้าง section จริงของบทความ — และลิงก์ 418 จุดยังคงเป็น [text](url) ที่ถูกต้อง ตารางสถิติฮอกกี้ 26×9 บนหน้า Scrape This Site forms page กลายเป็นตาราง pipe แบบ GFM ที่สะอาด 27 แถว (header + separator + 26 แถวข้อมูล) ครบทั้งช่องว่างและข้อมูล ความเร็วก็ไม่มีปัญหา: median 48 ms สำหรับหน้า quotes ขนาดเล็ก ไปจนถึง 352 ms สำหรับหน้า Wikipedia ขนาด 226 KB

แต่มีข้อแม้อยู่ และนี่เป็นการตัดสินใจด้านการออกแบบ ไม่ใช่บั๊ก MarkItDown ไม่ได้ตัด boilerplate ออก มันแปลง <body> ทั้งก้อน ดังนั้นส่วนประกอบของหน้าเว็บอย่างเมนู ปุ่ม ลิงก์ส่วนหัวส่วนท้ายก็ถูกพ่วงมาด้วย และปริมาณที่ติดมาจะมากขึ้นตามความรกของหน้า

หน้าจำนวนอักขระผลลัพธ์หัวข้อ (h1/h2/h3)ลิงก์สัดส่วนบรรทัดโค้ดส่วนเกิน
Books to Scrape10,4781 / 0 / 0940.6% (1/159)
Quotes to Scrape2,9731 / 1 / 0551.2% (1/86)
ScrapeThisSite forms3,3851 / 0 / 0316.7% (5/75)
Wikipedia Web scraping60,1591 / 7 / 1241812.4% (42/338)

บนหน้า Books ที่แทบไม่มีโค้ดส่วนเกินเลย 0.6% ของบรรทัดผลลัพธ์คือ chrome แต่บน Wikipedia ตัวเลขนี้พุ่งไปถึง 12.4% — 42 จาก 338 บรรทัดที่ไม่ว่างเป็นพวก "jump to content," "toggle the table of contents," "22 languages," "retrieved from," รวมถึง footer เรื่องคุกกี้และไลเซนส์ ป้ายดูแลบทความของ Wikipedia เช่น "This article needs additional citations" ก็ยังถูกแปลงอย่างซื่อสัตย์เป็นตาราง pipe แบบสองคอลัมน์ ซึ่งเป็นที่มาของแถวตาราง 9 แถวทั้งที่หน้าไม่มีตารางข้อมูลจริง

ทั้งหมดนี้ไม่ใช่สิ่งที่ MarkItDown ทำผิด มันเป็น whole-document converter ไม่ใช่ตัวดึงเฉพาะบทความ: การแปลง HTML เป็น Markdown แบบซื่อสัตย์ไม่ใช่งานเดียวกับการดึงบทความให้สะอาด Trafilatura และเครื่องมือแนว Firecrawl ตั้งใจคืนเฉพาะเนื้อหาหลัก ส่วน MarkItDown คืนทั้งหน้า ภายใน _html_converter.py ของมันจะลบ <script> และ <style> ออก แล้วส่ง <body> ทั้งก้อนให้ไลบรารี markdownify โดยไม่มี heuristic สำหรับหาเนื้อหาหลักอยู่ในเส้นทางเลย ถ้าคุณต้องการแค่บทความ นี่คือชั้นงานที่ผิด

ถิ่นของมันจริง ๆ: PDF, DOCX, XLSX, PPTX

เอกสารคือสิ่งที่ MarkItDown ถูกสร้างมาเพื่อจัดการ ผมทดสอบกับไฟล์สาธารณะจริง ๆ — บทความ arXiv ที่มี text layer, whitepaper ของ Bitcoin, ไฟล์ PDF สแกนที่เป็นรูปภาพล้วนซึ่งผมเรนเดอร์ให้ไม่มีข้อความเลย, และไฟล์ DOCX/XLSX/PPTX จากชุดทดสอบของ MarkItDown เอง (ฝัง UUID ไว้เพื่อจับการสูญหายของเนื้อหาแบบเงียบ ๆ)

เอกสารขนาดอินพุตจำนวนอักขระผลลัพธ์Probesเวลากลางหมายเหตุ
arXiv 1706.03762 (PDF มี text layer)2.2 MB40,1747/73.7 s (warm)title, "Transformer", "BLEU", "References" อยู่ครบ
Bitcoin whitepaper (PDF 9 หน้า)184 KB22,4856/61.4 s"Satoshi Nakamoto", "proof-of-work", "Conclusion" อยู่ครบ
PDF สแกน (ไม่มี text layer)89 KB00/415 msผลลัพธ์ว่าง ไม่มี error และไม่มี OCR
DOCX (test.docx)136 KB4,65170 msหัวข้อ + ตาราง GFM; UUID ที่ฝังไว้ยังอยู่ครบ
DOCX ที่มีสมการ15 KB240101 msOffice Math ถูกเก็บเป็น LaTeX
XLSX (test.xlsx)12 KB80857 msแต่ละชีต → ## SheetName + ตาราง GFM
PPTX (test.pptx)278 KB2,04752 msมีตัวบอกเลขสไลด์, ตาราง, แผนภูมิ → ตาราง

การดึงข้อความจาก PDF ที่มี text layer ทำได้ยอดเยี่ยม — probe ที่ตั้งไว้ล่วงหน้า 7 จาก 7 ตัวบนบทความ arXiv "Attention Is All You Need" และ 6 จาก 6 ตัวบน Bitcoin whitepaper ผ่านหมด และไฟล์ Office ก็ไม่สูญเสีย UUID sentinel สักตัว แปลว่าไม่มีการหายของเนื้อหาแบบเงียบ ๆ บน regression fixtures ของผู้ดูแลโครงการเอง จุดที่น่าสนใจอีกอย่างคือเส้นทาง DOCX (ผ่าน mammoth) ยังเก็บสมการ Office Math เป็น LaTeX แปลง equations.docx ออกมาเป็นสมการ $$...$$ จริง ๆ ถ้าคุณส่งเอกสาร Word ที่มีสมการเยอะให้ LLM นี่คือจุดแข็งที่เฉพาะทางแต่มีประโยชน์มาก และผมหาเอกสารอธิบายไว้ที่อื่นไม่เจอ

มี 2 เรื่องบนสนามนี้ที่ควรพูดแยก เพราะมันคือจุดที่น่าจะกัดคุณมากที่สุด

PDF สแกนที่หายไปเฉย ๆ

ถ้าคุณป้อน PDF ที่เป็นรูปภาพล้วน ไม่มี text layer ให้ MarkItDown มันจะตอบกลับมาเป็นสตริงว่าง ไม่มีอักขระเลย ไม่มี exception ไม่มีคำเตือน — แปลงเสร็จในราว 15 ms เพราะแทบไม่มีอะไรให้ดึงออกมา เส้นทาง PDF ของ MarkItDown เป็นแค่ text extraction (ใช้ pdfminer และ pdfplumber เบื้องหลัง) และไม่ได้พ่วง OCR มาให้ทั้งใน core install หรือ pip extra ใด ๆ

เรื่องนี้สำคัญมากเวลาใช้งานเป็นชุด ถ้านักพัฒนาป้อนโฟลเดอร์ PDF ที่มีทั้งไฟล์สแกนปนอยู่ ก็จะได้ผลลัพธ์ว่างแบบเงียบ ๆ สำหรับไฟล์เหล่านั้น โดยไม่มีสัญญาณบอกว่าอะไรถูกข้ามไป ผมเช็กแล้วว่าไม่ใช่ฟิกซ์เจอร์เสีย โดยสั่ง extract_text ของ pdfminer ตรง ๆ กับไฟล์นั้น — ตัวอักษรถูก strip ออกเป็นศูนย์ ไม่มี text layer ยืนยันชัดเจน — ดังนั้นผลลัพธ์ว่างจึงเป็นพฤติกรรมจริงของ MarkItDown ต่อไฟล์สแกนจริง ๆ นี่สะท้อนช่องว่าง OCR fallback ที่ค้างอยู่มานาน issue #1268 ซึ่งยังติดตามอยู่ทาง upstream ช่องทางที่มีเอกสารคือ Azure Document Intelligence backend แบบเลือกใช้ หรือ plugin; ทั้งสองอย่างไม่ได้มากับการติดตั้งปกติ

PDF ออกมาเป็นข้อความล้วน ไม่ใช่โครงสร้าง

ใน PDF ทั้งสองไฟล์ที่มี text layer MarkItDown ไม่ได้สร้าง Markdown heading marker ออกมาเลยสักตัว PDF ไม่มี semantic heading tags และ MarkItDown ก็ไม่พยายามเดาจากขนาดฟอนต์ ดังนั้นทุกบรรทัดจึงลงมาอยู่ระดับเนื้อหาปกติ การจำข้อความทำได้ดี แต่โครงสร้างแบนราบ

นี่ไม่ใช่แค่ผลลัพธ์ของผมอย่างเดียว เบนช์มาร์กสาธารณะจากบุคคลที่สามให้คะแนน hierarchy ของ heading ใน PDF ของ MarkItDown อยู่ราว 0.0 และ fidelity ของตารางราว 0.27 ซึ่งต่ำกว่า Docling ที่อาศัย TableFormer อย่างมากถึง 0.88 (ดู การเปรียบเทียบ MarkItDown vs Docling vs Marker และ READoc benchmark) ฟิกซ์เจอร์ของผมให้ผลตรงกัน ซึ่งเป็นจุดแข็งของหลักฐาน — ตัวเลขของผมสอดคล้องกับแหล่งภายนอก ข้อแลกเปลี่ยนที่เบนช์มาร์กชุดเดียวกันรายงานคือ MarkItDown เร็วกว่าประมาณ 100 เท่าเมื่อเทียบกับ Docling ซึ่งก็สอดคล้องกับเวลาที่ผมเห็นเป็นวินาที ไม่ใช่นาที สำหรับเอกสารที่เครื่องมือแบบ layout model ใช้เวลาหลายนาที ข้อสรุปคือ: MarkItDown ให้คุณได้ PDF ข้อความ ที่สะอาดและเร็ว แต่ไม่ได้ให้ โครงสร้าง ของ PDF ถ้าหัวข้อและตารางต้องอยู่ครบ เครื่องมือที่ใช้ layout model อย่าง Docling หรือ Marker คือชั้นที่เหมาะกว่า

ตาราง: ข้อความอยู่ครบเสมอ แต่โครงสร้างไม่เสมอไป

ตารางคือจุดที่คำว่า "ข้อความยังอยู่ครบไหม" กับ "ข้อมูลใช้ได้ไหม" แยกทางกันชัดที่สุด ผมจึงสร้างเมทริกซ์ 13 กรณี — หนึ่ง <table> ต่อหนึ่งกรณี และแต่ละอันถูกให้คะแนนเทียบกับ manifest ที่เขียนไว้ก่อนเริ่มรัน — เพื่อดูให้ชัดว่ารูปแบบไหนรอดและรูปแบบไหนพัง

MarkItDown table fidelity: tokens survive but rowspan can silently shift columns

ประเด็นหลักคือ: MarkItDown ไม่เคยทำให้เนื้อหาในตารางหายไป ทั้ง 13 กรณียังคง token ที่ลงทะเบียนไว้ล่วงหน้าได้ 100% แต่ความถูกต้องด้านโครงสร้างแบ่งเป็น 3 แบบ เจ็ดจากสิบสามกรณีออกมาเป็นกริด GFM ที่เรียบร้อย (plain, header-colspan, กว้าง 24 คอลัมน์, ไม่มีหัวตาราง, ช่องว่าง, block-in-cell, และ Arabic แบบขวาไปซ้าย) อีกสี่กรณีออกมาเป็นแถวที่ดูรุงรัง เพราะ Markdown ไม่มีแนวคิดเรื่องเซลล์ที่พาดหลายแถว/หลายคอลัมน์ จึงทำให้ rowspan, colspan และแหล่งข้อมูลที่เสียรูปออกมาเป็นแถวสั้น ๆ และอีกสองกรณีพังแบบชัดเจน

สองกรณีที่พังควรเรียกชื่อไว้ให้ชัด ตารางซ้อน (มี <table> อยู่ข้างใน <td>) จะถูกแบนราบเป็น inline ทำให้ pipe และแถว separator ของตารางย่อยไหลเข้าไปในเซลล์แม่ และเกิดแถวขยะที่เหมือนมี 14 "คอลัมน์" อีกกรณีคือเครื่องหมาย | แบบ literal ในเซลล์ไม่ได้ถูก escape — ข้อความ a | b จะกลายเป็นสองคอลัมน์ และ x || y จะกลายเป็นสามคอลัมน์ — ส่งผลให้ตารางสองคอลัมน์กลายเป็นแถวที่มีสอง สาม และสี่คอลัมน์ปนกัน และ parser Markdown ปลายทางจะอ่านขอบเขตผิดทั้งหมด น่าแปลกที่ asterisk และ backtick ในเซลล์ ถูก escape แต่ pipe กลับไม่ถูก สาเหตุหลักคือเส้นทาง HTML ของ MarkItDown ใช้การจัดการตารางแบบ default ของ markdownify โดย subclass ที่กำหนดเองไป override แค่ลิงก์ รูปภาพ และหัวข้อ แต่ไม่แตะเซลล์ตาราง ปัญหา pipe escaping แบบเดียวกันนี้ก็มีอยู่ใน issue เปิดของตัวแปลง CSV ด้วย #2019 แม้การแก้ตรงนั้นจะไม่กระทบเส้นทาง HTML ที่ผมทดสอบ

จุดที่ละเอียดกว่า และเป็นข้อค้นพบที่ผมอยากให้วิศวกรข้อมูลเห็นมากที่สุด คือ rowspan กรณี t03 ไม่ได้แค่ดูรุงรัง แต่มันทำให้ข้อมูลเหลื่อมแบบเงียบ ๆ ป้าย rowspan=2 (“Fruit”) ถูกปล่อยออกมาแค่ครั้งเดียว แล้วแถวด้านล่างกลายเป็นแถวสองคอลัมน์สั้น ๆ (| Banana | 8 |) ทำให้ "Banana" ไปอยู่ใต้คอลัมน์ Group แทนคอลัมน์ Item ทุก token ยังอยู่ครบ แต่ถ้ามีคนอ่านคอลัมน์ที่สองแบบง่าย ๆ ก็จะได้ค่าผิด นี่คือบั๊กแบบที่ผ่านด่านตรวจว่า "ข้อความยังไม่หาย" แต่ค่อย ๆ ทำให้ชุดข้อมูลเพี้ยน

ข้อจำกัดเรื่อง span เองก็เป็นข้อกำหนดด้านการออกแบบที่รู้กันและติดตามอยู่แล้ว (#1211, #1248) — เพราะกริด pipe แบบ GFM ที่แบนราบนั้นไม่สามารถแทน span หรือ nesting ได้จริง ๆ ตัว converter จึงแลกโครงสร้างกับความครบของเนื้อหาไป อย่างไรก็ตามก็ยังมีพฤติกรรมดี ๆ อยู่ด้วย: ตารางที่ไม่มีหัวจะถูกสร้างแถวหัวเปล่าขึ้นมาอัตโนมัติ (จึงไม่มีข้อมูลถูกดันขึ้นไปเป็นหัวแบบเงียบ ๆ), ช่องว่างถูกเก็บไว้ครบ และ <caption> ยังอยู่เป็นบรรทัดข้อความเหนือ ตาราง

การติดตั้งและตอนเริ่มทำงาน: ภาษีที่คำว่า "ยูทิลิตี้เบา ๆ" ไม่ได้บอกคุณไว้

ไม่มีจุดไหนที่ทำให้ผมแปลกใจมากไปกว่านี้ และนี่คือจุดที่ภาพจำว่าเป็น "ยูทิลิตี้ Python แบบเบา" ให้คำสัญญาเกินจริงแบบเงียบ ๆ

MarkItDown dependency footprint: 161 MB total, onnxruntime 73 MB and numpy 34 MB

อย่างแรก อย่าใช้ pip install 'markitdown[all]' บน Python 3.14 มันจะย้อนเวอร์ชันกลับไปเป็น markitdown 0.0.2 แบบเงียบ ๆ ซึ่งเป็นเวอร์ชันเมื่อสองปีก่อน และผมลองซ้ำแล้วใน venv ใหม่ที่สะอาด การ pin เวอร์ชันทำให้เห็นสาเหตุ: pip install 'markitdown[all]==0.1.6' จะ error เพราะ extra [all] ไป pin youtube-transcript-api~=1.0.0 ไว้ และบน PyPI ตอนนี้ทุก build ในช่วงนั้นถูกจำกัดให้ใช้ได้เฉพาะ Python <3.14 ส่วน build ที่ใช้กับ 3.14 ได้กลับอยู่นอกช่วง pin ดังนั้น resolver จึงถอยไปยัง release ล่าสุดที่ตอบสนองเงื่อนไขได้ทั้งหมด เรื่องนี้ตรงกับ issue upstream ที่เปิดไว้ #2179 วิธีแก้ตรงไปตรงมาคือ pin เวอร์ชันแล้วติดตั้ง extras ทีละตัว: pip install 'markitdown==0.1.6' จากนั้น pip install 'markitdown[pdf,docx,pptx,xlsx,xls]==0.1.6' แต่ละอัน resolve ได้ปกติ มีแค่ bundle [all] ตัวเดียวที่มี pin พิษอยู่ (และกับ Python เวอร์ชันอื่นผลอาจต่างออกไป — บน Python 3.13 หรือต่ำกว่า อาจไม่มีการชน gate แบบนี้)

อย่างที่สอง คือ footprint ตัว core install ใช้พื้นที่ 161 MB (venv ว่าง 13 MB บวกเพิ่มอีก 148 MB) ในนั้น onnxruntime (73 MB) กับ numpy (34 MB) รวมกันเป็น 107 MB หรือ 66% ของ footprint core ทั้งหมด และทั้งสองตัวถูกลากเข้ามาโดย dependency เดียวที่บังคับใช้: magika ตัวตรวจจับประเภทไฟล์ด้วย machine learning ของ Google ดังนั้นตัวแปลงข้อความจึงพก ONNX inference runtime ขนาด 73 MB ติดมาด้วยตั้งแต่ติดตั้งพื้นฐาน ก่อนที่คุณจะเพิ่ม document extra ตัวใดเลย พอใส่ document extras เพิ่ม venv จะขยับไปถึง 310 MB มันยังเบากว่า headless browser stack มาก แต่ถ้าคุณคิดว่าจะได้ยูทิลิตี้แบบ pip install แล้วใช้ได้เลย ก็ต้องรู้ไว้ว่ามี ONNX runtime ติดมาด้วย

อย่างที่สาม — และนี่คือข้อค้นพบเดียวในชุดงานนี้ที่ผ่านทุกการตรวจความแปลกใหม่ที่ผมลอง — แม้ติดตั้งแบบสะอาดแล้ว import markitdown ยังใช้เวลาประมาณ 3.35 วินาที บนเครื่องนี้ ค่าใช้จ่ายส่วนใหญ่อยู่ตอน import เอง: markitdown._markitdown จะ import registry ของ converter ทั้งหมดแบบ eager (รวม 2.56 วินาที หรือ 76% ของทั้งหมด) ซึ่งดึง pandas (594 ms ผ่านตัวแปลง XLSX), python-pptx (427 ms), magika (354 ms) และ requests (270 ms) เข้ามาทั้งหมด ไม่ว่าคุณจะใช้ฟอร์แมตเหล่านั้นจริงหรือไม่ สำหรับ service ที่รันยาว ๆ import ครั้งนี้เป็นต้นทุนที่เฉลี่ยทิ้งไปได้และแทบไม่สำคัญ แต่สำหรับการเรียกผ่าน CLI หรือ cold start บน serverless นี่คือภาษีต่อ process ที่คำว่า "ยูทิลิตี้เบา" ไม่ได้ทำให้คุณคาดไว้ (หมายเหตุที่ยุติธรรม: นี่เป็นการ profiling เพียงรอบเดียว ถือเป็นหนึ่ง observation ไม่ใช่การแจกแจงจากหลายรอบ)

MarkItDown cold start import tax: 3.35 seconds, registry 2.56 seconds

สเกลการใช้งาน: ไม่ล่ม แต่ต้องเผื่องบ CPU สำหรับ PDF และ RAM สำหรับสเปรดชีต

ผมผลักงานขนาดใหญ่ 4 ชิ้นผ่านเครื่อง โดยแต่ละชิ้นรันคนละ process เพื่อไม่ให้ค่า peak memory ปนจากการรันก่อนหน้า ไม่มีอะไรล่ม แต่ต้นทุนกลับเอียงชัดเจน

MarkItDown timing scale: arXiv 3.7 seconds, NIST 192.5 seconds, 50K XLSX plus 374 MB

หัวข้อขนาดอินพุตจำนวนอักขระผลลัพธ์เวลากลางPeak RSS Δ
NIST SP 800-53r5 (PDF 492 หน้า)5.9 MB1,625,365192.5 s+40 MB
XLSX 50,000 แถว × 8 คอลัมน์2.1 MB3,722,95562.1 s+374 MB
arXiv 1706.03762 (~PDF 15 หน้า)2.2 MB40,17412.6 s+25 MB
XLSX 200 แถว × 64 คอลัมน์46 KB120,1292.9 s+22 MB

PDF NIST 492 หน้า ใช้เวลา median 192.5 วินาที — ประมาณ 3.2 นาที หรือ 0.39 วินาที/หน้า — เพราะ pdfplumber ทำ form-detection แบบ word-position บนทุกหน้า Peak RSS อยู่แค่ +40 MB ดังนั้นมันติดคอขวดที่ CPU ไม่ใช่ memory แม้แต่ PDF arXiv 15 หน้าเองก็ใช้เวลา 12.6 วินาทีเมื่อรันใน process แยก ซึ่งมากกว่าเวลา 3.7 วินาทีที่ไฟล์เดียวกันใช้ตอน warm ในชุดทดสอบเอกสารของผมราว 3.4 เท่า ช่องว่างนี้คือต้นทุนของการเริ่ม process แบบเย็น และยืนยันว่าตัวขับหลักคือการทำงานรายหน้า ไม่ใช่ขนาดไฟล์ดิบ ถ้าคุณต้องการตัวเลขเดียวที่จะใช้แทนพฤติกรรมของ PDF นี้ ให้ใช้ 12.6 วินาทีจากการรันแบบแยก process

เส้นทางสเปรดชีตกลับกันอย่างสิ้นเชิง XLSX ขนาด 2.1 MB ที่มี 50,000 แถว พองขึ้นเป็น peak RSS +374 MB (และได้อักขระผลลัพธ์ 3.7 ล้านตัว) เพราะตัวแปลงโหลดชีตทั้งก้อนแล้วสร้างสตริง Markdown ยักษ์ขึ้นในหน่วยความจำ ดังนั้นคำแนะนำแบบสั้นแต่ตรงคือ: ถ้าเป็น PDF ใหญ่ เตรียมงบ CPU เป็นนาที; ถ้าเป็นสเปรดชีตใหญ่ เตรียม RAM หลายร้อย MB ตัวเลขเหล่านี้มาจากเครื่องเดียว บน macOS arm64 และ Python 3.14 และค่าคงที่ต่อหน้า/ต่อแถวก็ขึ้นกับแพลตฟอร์ม แต่รูปทรงของมัน — PDF ช้าและกิน CPU, XLSX หนัก memory, และไม่มีอะไรล่ม — เป็นส่วนที่นำไปใช้ต่อได้

Thunderbit เข้ามาเกี่ยวตรงไหน — และตรงไหนไม่เกี่ยว

ลองใช้ Thunderbit สำหรับดึงข้อมูลเว็บ

นี่เป็นการเปรียบเทียบที่ถ้าเผลอพูดเกินจริงได้ง่ายมาก ผมเลยขอวางเส้นให้ชัดเจน: MarkItDown กับ Thunderbit แก้ปัญหาคนละจุดที่อยู่ติดกัน แต่ไม่ใช่เรื่องเดียวกัน

MarkItDown แปลงไฟล์ที่คุณมีอยู่แล้ว ส่วน Thunderbit ดึง หน้าเว็บมาก่อน Thunderbit จุด /distill จะเปลี่ยนหน้าเว็บสดให้กลายเป็น Markdown ที่สะอาดและพร้อมใช้กับ LLM โดยรับมือทั้งการ render JS, anti-bot และเนื้อหาแบบ dynamic ที่ MarkItDown ไม่มีเครื่องมือรองรับ และจุด /extract ของมันจะคืน JSON ที่มี schema ตรงตามที่กำหนด ไม่ใช่แค่ Markdown ดิบ ๆ สำหรับนักพัฒนา ยังมีทั้ง API (POST /distill / POST /extract), MCP server และ CLI (npx @thunderbit/thunderbit-cli) บนเอนจิน AI เดียวกัน ซึ่งก็คือเอนจินที่อยู่เบื้องหลัง extension ที่มีผู้ใช้ 100,000+ ราย

ดังนั้นทั้งสองตัวจะซ้อนกันอยู่แค่จุดเดียวคือ ทั้งคู่สามารถส่งออก "Markdown ที่พร้อมใช้กับ LLM" ได้ แต่โดเมนอินพุตต่างกัน Thunderbit distill ใช้กับ URL บนเว็บสาธารณะ ส่วน MarkItDown ใช้กับ ไฟล์ในเครื่อง มันไม่ใช่ของแทนกันตรง ๆ และผมจะไม่ทำทีเหมือนมันเป็นแบบนั้น สแต็กที่ใช้งานจริงคือใช้ทั้งคู่ร่วมกัน: ดึงและ crawl เว็บด้วย Thunderbit (หรือบริการแนว Firecrawl) แล้วค่อยทำให้เอกสารท้องถิ่นที่คุณมี — PDF, deck, สเปรดชีต — อยู่ในรูปมาตรฐานด้วย MarkItDown ตัวหนึ่งจัดการเครือข่าย อีกตัวจัดการตู้เก็บไฟล์

ข้อดีและข้อเสีย

จุดแข็ง

  • ดึงเนื้อหาหลักจาก HTML ที่สะอาดได้ครบถ้วน 4/4 หน้า พร้อมเก็บโครงสร้างหัวข้อและลิงก์ได้ตรง
  • ดึงข้อความจาก PDF/DOCX ได้ดีมาก (arXiv ผ่าน 7/7 probes, Bitcoin 6/6) และไม่มีการสูญหายของเนื้อหาแบบเงียบ ๆ บนไฟล์ Office ของผู้ดูแลเอง
  • สมการ Office Math ถูกเก็บเป็น LaTeX ซึ่งเป็นข้อดีเฉพาะทางที่มีประโยชน์จริง
  • ไม่ล่มแม้กับงานขนาดใหญ่ ทั้ง PDF 492 หน้า และ XLSX 50k แถว
  • เรียกใช้งานง่ายมาก: CLI, convert(), pipe จาก stdin และ MCP server แบบเลือกใช้ได้
  • ใช้สัญญาอนุญาต MIT, Microsoft ดูแลต่อเนื่อง, issue tracker ตอบสนองดี

จุดอ่อน

  • เก็บ boilerplate ติดมาด้วย — Wikipedia สูงสุดถึง 12.4% ของบรรทัด output เป็น chrome; ไม่ใช่ตัวดึงบทความ
  • ตารางพังเมื่อมี spans, nesting และ pipe ในเซลล์ (พัง 2/13, ดูรุงรัง 4/13) และ rowspan ทำให้ข้อมูลเหลื่อมแบบเงียบ ๆ
  • PDF สแกน/รูปภาพล้วนให้ผลลัพธ์ว่าง ไม่มี OCR และไม่มี error แจ้ง
  • Output ของ PDF ไม่มีโครงสร้าง heading เลย (ตรงกับเบนช์มาร์กสาธารณะ)
  • core install 161 MB โดยมี ONNX runtime 73 MB พ่วงมา; cold import ราว 3.35 วินาที
  • extra [all] บน Python 3.14 ถอยกลับไปเป็น 0.0.2 ที่เก่าไปสองปีแบบเงียบ ๆ

ใครควรใช้ และใครไม่ควรใช้

ควรใช้ MarkItDown ถ้าคุณกำลังทำให้เอกสารท้องถิ่นปนกันหลายแบบ — Word, Excel, PowerPoint, PDF ที่มี text layer — กลายเป็น Markdown สำหรับ pipeline ของ LLM และคุณสนใจความครบของข้อความมากกว่ารูปแบบโครงสร้าง ในบทบาท converter ขั้นสุดท้ายของงานแบตช์ที่ป้อนข้อความสะอาดให้โมเดล มันเร็ว แม่น และใช้งานได้ฟรี

แต่ถ้างานของคุณเป็นข้อใดข้อหนึ่งต่อไปนี้ ให้ข้ามมันไป หรือใช้ร่วมกับเครื่องมืออื่น: คุณต้องการแค่บทความหลักจากหน้าเว็บ (ใช้เครื่องมือแนว readability หรือ Firecrawl); คุณต้องการให้หัวข้อและตารางใน PDF อยู่ครบแบบไม่เพี้ยน (นี่คือพื้นที่ของ Docling หรือ Marker); หรืออินพุตของคุณมีเอกสารสแกนที่ต้องใช้ OCR (คุณจะต้องใช้ Azure backend หรือเครื่องมืออื่นไปเลย) และถ้าคุณคิดว่ากำลังซื้อสแครปเปอร์ — เครื่องมือที่ดึงเว็บและไล่หน้า — นี่ไม่ใช่แบบนั้นเลย

คะแนนทดลองที่ผมให้จาก rubric แบบสแครปเปอร์อยู่ที่ 60/100 และคะแนนต่ำนี้เกิดจากการเอา converter ไปให้คะแนนด้วยข้อสอบของ crawler เมื่อมองในสนามของมันเอง คะแนนความแม่นของข้อความกลับสูงมาก จุดอ่อนของมันคือเรื่องโครงสร้าง (ตาราง, heading ของ PDF) และแพ็กเกจจิง (footprint, import, กับกับดัก [all]) ไม่ใช่คุณภาพข้อความ ถ้าคุณมองมันตามสิ่งที่มันเป็นจริง — ตัวแปลงไฟล์เป็น Markdown — มันคือเครื่องมือที่แข็งแรง ดูแลต่อเนื่อง และมีขอบคมเล็กน้อยที่คุณควรรู้ก่อนเอาเข้าระบบ production

คำถามที่พบบ่อย

MarkItDown เป็นเว็บสแครปเปอร์หรือเปล่า?

ไม่ใช่ มันไม่มี crawler, ไม่มีการ render JavaScript, ไม่มีการไล่ลิงก์ และไม่มี pagination มันแปลงไฟล์และเอกสารที่คุณมีอยู่แล้ว — PDF, DOCX, XLSX, PPTX, รูปภาพ, HTML — ให้เป็น Markdown ถ้าคุณต้องการดึงและ crawl หน้าเว็บสด คุณควรใช้เครื่องมือสแครปปิ้งอย่าง Thunderbit หรือ Firecrawl; MarkItDown คือขั้นตอนถัดไป หลังจากดึงไฟล์หรือหน้าเว็บมาแล้ว เพื่อแปลงให้เป็น Markdown ที่สะอาด

ทำไม pip install markitdown[all] ถึงติดตั้งเวอร์ชันเก่า?

บน Python 3.14 extra [all] จะ pin youtube-transcript-api~=1.0.0 ไว้ และทุก build ในช่วงนั้นถูกจำกัดให้ใช้ได้กับ Python ต่ำกว่า 3.14 ตัว resolver จึงไม่สามารถทำให้ครบเงื่อนไขได้ และถอยกลับไปที่ markitdown 0.0.2 ซึ่งเป็น release เมื่อสองปีก่อนแบบเงียบ ๆ วิธีแก้คือ pin เวอร์ชันแล้วติดตั้ง extras ทีละตัว: pip install 'markitdown==0.1.6' แล้วค่อยเพิ่ม 'markitdown[pdf,docx,pptx,xlsx,xls]==0.1.6' เรื่องนี้ติดตามอยู่ใน issue #2179

MarkItDown ทำ OCR กับ PDF ที่สแกนไหม?

ไม่ทำในชุดติดตั้งปกติ เส้นทาง PDF ของมันเป็น text extraction ล้วน ดังนั้น PDF ที่เป็นรูปภาพอย่างเดียวและไม่มี text layer จะได้สตริงว่าง — ไม่มี error ไม่มีคำเตือน OCR ต้องใช้ Azure Document Intelligence backend แบบเลือกใช้ หรือ plugin ซึ่งไม่มีมาให้ในค่าเริ่มต้น นี่เป็นช่องว่างที่ติดตามมานานแล้ว (issue #1268)

MarkItDown จัดการตารางได้ดีแค่ไหน?

ถ้ามองด้านเนื้อหา ถือว่าดีมาก — ในการทดสอบ 13 กรณีของผม มันเก็บเนื้อหาตารางครบ 100% ทุกกรณี แต่ถ้ามองด้านโครงสร้าง มันขึ้นกับรูปทรง: ตารางแบบง่าย แบบกว้าง แบบไม่มีหัว และแบบมีช่องว่าง จะออกมาเป็นกริด GFM ที่สะอาด แต่ rowspan และ colspan จะออกมารุงรัง (และ rowspan อาจทำให้ข้อมูลเหลื่อมไปคอลัมน์ผิดแบบเงียบ ๆ), ตารางซ้อนถูกแบนเป็นแถวขยะ, และ pipe แบบ literal ในเซลล์ก็ไม่ได้ถูก escape Markdown รูปแบบตารางที่แบนราบไม่สามารถแทน span หรือ nesting ได้อยู่แล้ว

MarkItDown เร็วพอสำหรับเอกสารขนาดใหญ่ไหม?

มันไม่ล่มกับไฟล์ใหญ่ แต่ต้องเผื่อทรัพยากรตามชนิดงาน PDF 492 หน้าใช้เวลาประมาณ 3.2 นาที (ราว 0.39 วินาที/หน้า) เพราะมีการตรวจจับฟอร์มรายหน้า และติดคอขวดที่ CPU ส่วนสเปรดชีต 50,000 แถวใช้เวลาประมาณหนึ่งนาที แต่กิน RAM เพิ่ม +374 MB เพราะมันสร้าง Markdown string ก้อนใหญ่ไว้ในหน่วยความจำ ถ้าเป็น PDF ใหญ่ให้วางแผนเรื่อง CPU เป็นนาที ถ้าเป็นสเปรดชีตใหญ่ให้วางแผน RAM หลายร้อย MB

ลองใช้ Thunderbit สำหรับดึงข้อมูลเว็บ Get Started Free

Ke
Ke
CTO ที่ Thunderbit | นักวิทยาศาสตร์ข้อมูลอาวุโสและผู้เชี่ยวชาญด้านแมชชีนเลิร์นนิง ด้วยประสบการณ์เกือบสิบปีในด้านแมชชีนเลิร์นนิงและวิทยาศาสตร์ข้อมูล เคเฉินเป็นศิษย์เก่ามหาวิทยาลัยโคลัมเบีย และอดีตนักวิทยาศาสตร์ข้อมูลอาวุโสที่ Walmart Labs ด้วยความเชี่ยวชาญลึกซึ้งที่ได้รับการยอมรับจากเพื่อนร่วมสายงานใน Python, R, Java และสถิติ เขาจึงแบ่งปันมุมมองที่ผ่านการพิสูจน์มาแล้วในการพัฒนาอัลกอริทึม AI ที่ซับซ้อนจากแนวคิดไปสู่สถาปัตยกรรมระดับใช้งานจริง

ลองใช้ Thunderbit

ดึงลีดและข้อมูลอื่น ๆ ได้ใน 2 คลิก ขับเคลื่อนด้วย AI.

รับ Thunderbit ใช้ฟรี
ดึงข้อมูลด้วย AI
ส่งข้อมูลไปยัง Google Sheets, Airtable หรือ Notion ได้อย่างง่ายดาย
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week