
في الآونة الأخيرة ، في أحد الشركات الناشئة ، تمكنت من حل مشكلة إنشاء تذاكر بتنسيق PDF. في ذلك الوقت ، كان هناك بالفعل موقع ويب به مجموعة كبيرة من التقنيات الجاهزة ، لذا كنت أبحث عن نهج لا يتطلب استخدام أدوات إضافية. في النهاية ، اقترحت إنشاء تذاكر بتنسيق HTML أولاً ، ثم التحويل إلى PDF باستخدام متصفح Chrome. كما اتضح فيما بعد ، وبهذه الطريقة ، يمكنك إنشاء ليس فقط تذاكر مزينة بثراء باستخدام CSS ، ولكن أيضًا مجموعة متنوعة من التقارير مع مخططات في JavaScript. في هذه المقالة ، سأتحدث عن كيفية تشغيل Chrome لهذه الأغراض ، وإعطاء بعض النصائح لتخصيص CSS ، وكذلك مناقشة عيوب هذا الحل.
لن يتم مناقشة الخيارات البديلة هنا ، نظرًا لأنه قد تم بالفعل كتابة ما يكفي منها ، فمن السهل العثور عليها ، وهي أدوات جاهزة ، ومعلومات من الأفضل البحث عنها في المصادر - في الوثائق الموجودة على المواقع الرسمية. الطريقة المقترحة ليست أداة مستقلة وهي أشبه بمنتج ثانوي لتطوير العديد من التقنيات. في الجزء باللغة الروسية من الإنترنت ، هناك القليل من المعلومات التي تم جمعها حولها ، لذلك قررت ملء الفراغ.
لماذا يتم اختيار هذا الخيار؟
أكبر ميزة هي أن Chrome لا يحتاج إلى توسيع مجموعة التكنولوجيا لإنشاء ملفات PDF. يقوم مطورو Frontend بإنشاء HTML باستخدام أدوات تطوير مألوفة ويرون على الفور النتائج الوسيطة للعمل في المتصفح. في الوقت نفسه ، ربما يكون Chrome يدور في اختبارات ونقله إلى الواجهة الخلفية ليس بالأمر الصعب. تجدر الإشارة أيضًا إلى أن المبرمج قادر على الوصول إلى ترسانة خصائص css بالكامل بما في ذلك Flexbox و Grid.
سأتحدث عن أوجه القصور وطرق الالتفاف عليها خلال المقال.
نحن نحل المشكلة في سطر واحد
في سطر الأوامر ، ندعو Chrome في وضع مقطوع الرأس مع حفظ الصفحة بتنسيق pdf:
chrome --headless --disable-gpu --print-to-pdf https://google.com
قد يحتاج مستخدمو Linux إلى تشغيل chromium-browser
بدلاً من chrome
.
قد يجد مستخدمو MAC أنه من المفيد إنشاء اسم مستعار مسبقًا:
alias chrome="/Applications/Google\\ \\Chrome.app/Contents/MacOS/Google\\ \\Chrome"
استكمال: أوضحت التعليقات أن مستخدمي Windows بحاجة إلى تعيين اسم ملف PDF بشكل --print-to-pdf=output.pdf
إذا كان لديك بالفعل مُنشئ مستندات HTML ، بدلاً من https://google.com
فحدد عنوان URL لاستلام هذا المستند.
افتح الملف output.pdf
في الدليل المحلي وانظر إلى النتيجة.
أول ما يلفت انتباهك هو وجود رأس مع تاريخ الطباعة وتذييل مع عنوان URL والصفحة. لإزالتها تحتاج إلى إضافة بعض قواعد CSS. من غير المرجح أن تتم إضافة هذه القواعد إلى google.com
، لذا من الأفضل إنشاء مستند HTML خاص بك لمزيد من العمل.
أضف CSS
يحتوي CSS على استعلام وسائط خاص @page
، يُستخدم للطباعة ؛ وسنقوم بتعيين المسافة البادئة فيه بحيث لا يتلاءم Header and Footer:
@page { size: A4; margin: 0mm; }
ستعمل هذه الطريقة فقط للمستندات ذات الصفحة الواحدة ، عند طباعة صفحتين أو أكثر ، سيظل تذييل الصفحة بعنوان URL وترقيم الصفحة في الأسفل. يمكنك مطالبة Chrome بشكل صريح بإيقاف تشغيل عرض رأس وتذييل الصفحة عن طريق تعيين عرض معلمة الطباعة displayHeaderFooter = False
، ولكن في الوقت الحالي لا يتم نقله إلى واجهة سطر الأوامر. للوصول إليه ، ستحتاج إلى أدوات لأتمتة العمل باستخدام المتصفح: السيلينيوم أو العرائس. بعد ذلك ، سأدرس الخيار الأول ، لأن مشروعي استخدم Python.
قم بتشغيل Chrome عبر السيلينيوم
لذلك ، قم بتثبيت Selenium باستخدام الأمر pip install selenium
، وقم بتنزيل برنامج تشغيل chrome الذي يطابق إصدار Chrome من http://chromedriver.chromium.org/ واستخدم وظيفة get_pdf_from_html
من المثال التالي:
import sys from selenium import webdriver from selenium.webdriver.chrome.options import Options import json, base64 def get_pdf_from_html(path, chromedriver='./chromedriver', print_options = {}):
للحصول على ملف PDF ، يمكنك تشغيل هذا المثال من سطر الأوامر عن طريق تحديد عنوان url واسم الملف لحفظ ملف PDF ، أو استدعاء وظيفة get_pdf_from_html
وتمرير ثلاث وسائط:
- المسار - عنوان url للمستند html؛
- chromedriver - المسار على الجهاز المحلي إلى برنامج تشغيل chrome (بشكل افتراضي ، يجب أن يكون في الدليل المحلي) ؛
- print_options - سمات طباعة إضافية.
تجدر الإشارة إلى أن السيلينيوم لا يحتوي على واجهة قياسية لطباعة صفحة بتنسيق PDF ، ولا يستطيع Chrome القيام بذلك ، لذلك يتعين عليك الاتصال مباشرة بـ driver.command_executor._request
.
الآن ، لنرى الأدوات المتاحة للتحكم في موضع المحتوى في المستندات متعددة الصفحات.
CSS الطباعة
عند الطباعة على الوجهين ، يمكنك تعيين هوامش مختلفة من الحافة للصفحات اليمنى واليسرى بشكل فردي إذا كنت تخطط لخياطةها في المستقبل:
@page :left { margin-left: 4cm; margin-right: 2cm; } @page :right { margin-left: 4cm; margin-right: 2cm; }
بالنسبة للصفحة الأولى ، يمكنك تحديد التصميم الخاص بك ، على سبيل المثال ، المسافة البادئة المتزايدة من الحافة العلوية:
@page :first { margin-top: 10cm }
من الممكن تعيين فاصل الصفحات قبل عنوان المستوى الأول بحيث يبدأ على صفحة فردية:
h1 { page-break-before : right }
باستخدام خاصية page-break-after
، يمكنك منع فاصل الصفحات مباشرة بعد بعض العناصر ، على سبيل المثال ، رأس المستوى الثاني:
h2 { page-break-after : avoid }
تساعد خاصية page-break-inside
على تجنب فواصل الصفحات حيثما يكون ذلك غير مرغوب فيه ، على سبيل المثال في منتصف الجدول
table { page-break-inside : avoid }
ستساعد orphans
منع فواصل الصفحات في بداية ونهاية الفقرة:
@page { orphans:4; widows:2; }
ماذا عن الأداء؟
على Core i5-8600K 3600MHz في دفق واحد ، يستغرق تحويل مستند بسيط واحد 0.6 ثانية. على آلة كاتبة محمولة بنهاية 2013 ، 2.4 جيجا هرتز - 1.5 ثانية.
من الواضح أن الموارد الرئيسية تنفق على تشغيل المتصفح. يمكنك تقليل وقت التحويل لعدد كبير من الملفات إذا قمت بتشغيل Chrome مرة واحدة كخدمة micros وإرسالها عنوان URL للتحويل. تنفيذ هذه الطريقة هو خارج نطاق هذه المقالة.
ما هو الخطأ؟
أرى مشكلتين رئيسيتين:
- استحالة ببساطة تحديد موضع العناصر في الوثيقة. هذا يجعل من الصعب إنشاء جدول محتويات مع إشارة تلقائية لأرقام الصفحات ، خاصة إذا كان حجم المحتوى غير معروف مقدمًا.
- يعد تحويل Chrome منتجًا من منتجات Google ، حيث يجمع مجموعة متنوعة من المعلومات حول المستخدمين. إذا كان تسرب البيانات من المستند غير مقبول ، فيجب أن تكون حذراً بشأن الحل المقترح - أغلق المتصفح بالوصول إلى الموارد الخارجية ، أو حتى ابحث عن حل آخر. استخدام برنامج مفتوح المصدر لا يحل Chromium المشكلة - تم العثور على أخطاء من Google بالفعل.
النتائج
أقترح استخلاص استنتاجات بشأن مقبولية استخدام هذا النهج بمفردي. كل مشروع فريد بطريقته الخاصة. ما إذا كانت هذه الطريقة مناسبة في مشروعك ، فذلك أمر متروك لك.