تحليل 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 الخاصة بها.
أيضاً في المكتبة
توصيات