بارسنج باستخدام Rust: أسرع من Python وبدون جامع القمامة

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

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

ابدأ الدورة

لماذا Rust هو الملك الجديد للبارسنج؟

\n\n

إذا كنت قد كتبت يومًا محللًا (parser) بلغة Python، فأنت تعرف هذه اللحظة: البرنامج النصي يعمل، البيانات تُسحب، ولكن فجأة — خطأ في الذاكرة، أو جامع القمامة يقرر أن "يأخذ قسطًا من الراحة" في أكثر الأوقات غير المناسبة. هل هذا مألوف؟ والآن تخيل أن المحلل الخاص بك يطير بسرعة لغة C، ولا يستهلك ذاكرة زائدة، وفي نفس الوقت آمن. مرحبًا بك في عالم البارسنج باستخدام Rust.

\n\n

Rust ليست مجرد لغة عصرية. لمهام استخراج البيانات، تمنحك ما لن تستطيع Python تقديمه أبدًا: تحكم كامل في الذاكرة، تكاليف إضافية صفرية لجامع القمامة، وسرعة لا تصدق. وفي الوقت نفسه، فإن النظام البيئي للعمل مع HTTP وHTML ناضج بالفعل بما يكفي. في هذه المقالة، سأوضح لك كيفية بناء محلل حقيقي باستخدام Rust يمكنك استخدامه لمراقبة الأسعار، جمع المحتوى، أو تحليل SEO.

\n\n

ما سنحتاجه: أدوات Rust للبارسنج

\n\n

لـ استخراج بيانات الويب باستخدام Rust هناك ثلاثة أركان:

\n\n
    \n
  • reqwest — عميل HTTP. يمكنه زيارة المواقع، ويدعم عدم التزامن والبروكسي.
  • \n
  • scraper (أو select.rs) — مكتبة لبارسنج HTML. تسمح باستخدام محددات CSS.
  • \n
  • tokio — بيئة تشغيل غير متزامنة. بدونها، سيبطئ المحلل الخاص بك عند كل طلب.
  • \n
\n\n

لننشئ مشروعًا جديدًا ونثبت التبعيات:

\n\n
cargo new rust_parser\ncd rust_parser\ncargo add reqwest --features json\ncargo add scraper tokio
\n\n

تم. الآن لدينا كل شيء لكتابة محلل باستخدام Rust في 10 دقائق.

\n\n

المحلل الأول: الحصول على العناوين من Habr

\n\n

لنبدأ بشيء بسيط: سنستخرج عناوين المقالات من Habr. هذا كلاسيكي من نوعه، مثل "Hello, World!" لـ استخراج البيانات باستخدام Rust.

\n\n
use scraper::{Html, Selector};\nuse reqwest;\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    // 1. إرسال طلب GET\n    let resp = reqwest::get("https://habr.com/ru/articles/")\n        .await?\n        .text()\n        .await?;\n\n    // 2. بارسنج HTML\n    let document = Html::parse_document(&resp);\n\n    // 3. إنشاء محدد للعناوين\n    let selector = Selector::parse("h2.article-title a").unwrap();\n\n    // 4. التكرار والعرض\n    for element in document.select(&selector) {\n        let title = element.text().collect::<Vec<_>>().join("");\n        println!("{}", title.trim());\n    }\n\n    Ok(())\n}
\n\n

ماذا يحدث هنا؟ نستخدم reqwest للطلب غير المتزامن، scraper لتحليل HTML ومحدد CSS h2.article-title a للعثور على جميع الروابط في العناوين. نشغل cargo run — ونرى قائمة المقالات. سريع، أليس كذلك؟

\n\n

البارسنج غير المتزامن: تحميل 100 صفحة في الثانية

\n\n

الميزة الرئيسية لـ البارسنج باستخدام Rust هي عدم التزامن. في Python كنت ستستخدم asyncio و aiohttp، لكن Rust مع tokio يمنحك تحكمًا أكبر. لنستخرج عدة صفحات بالتوازي.

\n\n
use scraper::{Html, Selector};\nuse reqwest;\nuse tokio::task;\n\nasync fn fetch_page(url: &str) -> Result<String, reqwest::Error> {\n    let resp = reqwest::get(url).await?.text().await?;\n    Ok(resp)\n}\n\nfn parse_titles(html: &str) -> Vec<String> {\n    let document = Html::parse_document(html);\n    let selector = Selector::parse("h2.article-title a").unwrap();\n    document\n        .select(&selector)\n        .map(|el| el.text().collect::<Vec<_>>().join("").trim().to_string())\n        .collect()\n}\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let urls: Vec<String> = (1..=5)\n        .map(|i| format!("https://habr.com/ru/articles/page{}/", i))\n        .coll                

المدونات

توصيات الكتب