تحليل HTML في C++: المكتبات والأمثلة للعمل مع DOM و XPath

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

تحليل HTML في C++: نظرة عامة على الأدوات وأمثلة عملية



تحليل HTML بلغة C++ هي مهمة يواجهها المطورون عند إنشاء محللات لصفحات الويب، أو محللات المحتوى، أو أدوات جمع البيانات الآلية. على عكس Python أو JavaScript، لا توجد مكتبة مدمجة في C++ للعمل مع مستندات HTML، ومع ذلك، هناك العديد من الحلول الناضجة وعالية الأداء. في هذه المقالة، سنستعرض المكتبات الرئيسية لتحليل HTML في C++، وميزاتها، ونقدم أمثلة على الكود.



المكتبات الرئيسية لتحليل HTML في C++



يعتمد اختيار المكتبة على مهامك: هل تحتاج إلى دعم محددات CSS، أو XPath، أو العمل مع HTML تالف، أو أقصى سرعة. دعنا نستعرض الخيارات الأكثر شيوعًا.



  • Gumbo-parser — مكتبة من Google، تطبق تحليل HTML5 وفقًا للمواصفات. توفر شجرة DOM بعد التحليل، ولكنها لا تتضمن أدوات مدمجة للتنقل عبر المحددات. تتطلب اجتياز العقد يدويًا.
  • MyHTML — شوكة (fork) من Gumbo مع دعم محسّن لمحددات CSS وواجهة برمجة تطبيقات أكثر ملاءمة. تسمح بالبحث عن العناصر حسب الفئات والوسوم والسمات.
  • Lexbor — مكتبة حديثة تركز على السرعة والامتثال للمعايير. تدعم كلاً من HTML ومحددات CSS، بالإضافة إلى XPath (من خلال وحدة إضافية).
  • htmlcxx — مكتبة بسيطة لتحليل HTML إلى شجرة. مناسبة للمشاريع الصغيرة، ولكنها لا تدعم HTML5.
  • Boost.PropertyTree (مع محلل XML) — يمكن استخدامه لتحليل XHTML، ولكنه غير مخصص لـ HTML غير الصالح.


التثبيت والتضمين



دعنا ننظر في تثبيت اثنتين من أشهر المكتبات: Gumbo-parser و MyHTML. للمشاريع التي تستخدم C++17، يُوصى باستخدام مدير الحزم vcpkg أو Conan.



// التثبيت عبر vcpkgvcpkg install gumbo-parservcpkg install myhtml

// التضمين في CMakeLists.txtfind_package(gumbo REQUIRED)target_link_libraries(your_project PRIVATE gumbo)

find_package(myhtml REQUIRED)target_link_libraries(your_project PRIVATE myhtml)


مثال 1: تحليل HTML باستخدام Gumbo-parser (اجتياز DOM يدويًا)



في هذا المثال، سنقوم بتحليل مستند HTML بسيط واستخراج جميع النصوص من الوسوم <p>.



#include <iostream>#include <string>#include <gumbo.h>

void extract_text(GumboNode* node) { if (node->type == GUMBO_NODE_TEXT) { std::cout << node->v.text.text; return; } if (node->type == GUMBO_NODE_ELEMENT && node->v.element.tag == GUMBO_TAG_P) { // معالجة العقد الفرعية GumboVector* children = &node->v.element.children; for (unsigned int i = 0; i < children->length; ++i) { extract_text(static_cast<GumboNode*>(children->data[i])); } std::cout << std::endl; return; } // اجتياز تكراري للعناصر الأخرى if (node->type == GUMBO_NODE_ELEMENT) { GumboVector* children = &node->v.element.children; for (unsigned int i = 0; i < children->length; ++i) { extract_text(static_cast<GumboNode*>(children->data[i])); } }}

int main() { std::string html = R"(<html><body><p>الفقرة الأولى</p><p>الفقرة الثانية</p></body></html>)"; GumboOutput* output = gumbo_parse(html.c_str()); extract_text(output->root); gumbo_destroy_output(&kGumboDefaultOptions, output); return 0;}


مثال 2: استخدام MyHTML مع محددات CSS



يوفر MyHTML واجهة أكثر ملاءمة للبحث عن العناصر. في هذا المثال، سنجد جميع الروابط ذات الفئة link ونعرض السمة href الخاصة بها.



توصيات