آموزش وب اسکرپینگ با سی شارپ – مقدماتی و به بیان ساده
وب اِسکرِپینگ، تکنیکی است که در آن، از رباتها به منظور استخراج محتوا و دادههای وبسایتی دلخواه، استفاده میشود. این کار به صورت دستی نیز قابل انجام است، اما خودکار کردن این فرایند، علاوه بر سرعت بیشتر و بهینگی، خطای کمتری را به دنبال دارد. عملکرد وب اِسکرِپینگ به گونهای است که کدهای HTML نهفته در صفحات وب را بیرون میکِشد و دادههای موجود در این صفحات، که ممکن است ساختاری ضعیف و غیرجدولی داشته باشند را بهصورت قالبی ساختاریافته در میآورد که برای کاربردهای گوناگون، مناسبتر خواهد بود. وب اسکرپینگ با سی شارپ فرایندی فراتر از جمعآوری دادهها است و میتواند در بایگانی دادهها و ردیابی آنلاین تغییرات آنها نیز به ما کمک کند. در این مطلب، به بیانی ساده و بهصورت گام به گام، آموزش وب اسکرپینگ با سی شارپ را با استفاده از کتابخانههایی، نظیر «سلنیوم» (Selenium) و Html Agility Pack، خواهیم داشت و با ایجاد یک خزندهوب، دادههای مورد نظر را از یک وب سایت نمونه استخراج میکنیم. همچنین مفاهیم پیشرفتهتری مانند اسکرپینگ موازی، اسکرپینگ وبسایتهای پویا و راهکارهایی به منظور پرهیز از بلاک شدن را نیز بررسی خواهیم کرد.
- خواهید توانست محیط توسعه وب اسکرپینگ را با سی شارپ راهاندازی کنید.
- میآموزید چگونه داده محصولات را با کدنویسی از HTML استخراج کنید.
- یاد خواهید گرفت دادههای جمعآوریشده را با CsvHelper در فایل CSV ذخیره کنید.
- تکنیکهای اسکرپینگ موازی و ضدبلاک را در پروژه خود پیاده خواهید کرد.
- یاد میگیرید با Selenium به استخراج داده از سایتهای داینامیک بپردازید.
- خواهید آموخت کد نهایی اسکرپینگ را ترکیب و برای پروژه واقعی آماده کنید.


آشنایی با وب اسکرپینگ
وب اسکرپینگ، فرایند استخراج داده از وبسایتها با استفاده از ابزارها و نرمافزارهای خودکار است. در دنیای پُرشتاب و دادهمحور امروز، وب اِسکرِپینگ به ابزاری ضروری برای کسب و کارها، محققان و تحلیلگران تبدیل شده است تا دیدگاههای ارزشمندی را از دادههای حجیم موجود در اینترنت، بیرون بِکشند.
تحلیلهای صورت گرفته با استفاده از دادههای Scrape شده، در مقاصد مختلفی مانند شناسایی مشتریان بالقوه، اطلاع از روند قیمتگذاری در بازار، تحلیل احساسات مشتری و دهها مورد دیگر قابل استفاده هستند. Web Scraping به طور روز افزون توسط محققان، به منظور ایجاد «مجموعه دادهها» (Data Sets)، برای پروژههایی مانند «متنکاوی» (Text Mining) و غیره استفاده میشود. این دادهها، ممکن است مجموعهای از مقالات ژورنالی یا متون دیجیتالی باشند.
سی شارپ (و به طور کلی دات نت)، تمامیابزارها و کتابخانههای لازم برای پیادهسازی وب اِسکرِپینگ را فراهم و به شما کمک میکند تا به سرعت پروژه Scraper خود را پیادهسازی و دادههای مورد نظر را جمعآوری کنید.
یکی از موضوعاتی که در این نوشتار به آن پرداخته شده است، تکنیکهای مختلف برای پیشگیری از «انسداد» (Block شدن) و همینطور محدود شدن توسط سرور است. این قضیه، به عنوان یکی از موانع اصلی در مبحث وب اِسکرِپینگ، بهشمار میرود.
امروزه، شرکتهای زیادی هستند که از مزایای دادههای جمعآوری شده از وب، بهره میگیرند. سی شارپ، یکی از مناسبترین زبانهای برنامهنویسی برای پیاده سازی Web Scraping است.

کتابخانه Html Agility Pack، محبوبترین کتابخانه Scraper برای سی شارپ است. با استفاده از این کتابخانه، میتوانید صفحات وب مورد نظر را دانلود و محتوای HTML آنها را تجزیه کنید، به طوریکه، پس از انتخاب عناصر HTML، بتوان دادههای مورد نیاز را از آنها استخراج کرد.
Selenium WebDriver، کتابخانهی دیگری است که از چندین زبان برنامهنویسی پشتیبانی میکند و به شما امکان میدهد تستهای خودکار برای وب اپلیکیشن بنویسید. همچنین میتوانید از آن برای اهداف وب اسکرپینگ نیز استفاده کنید.
تصویر زیر برخی از کاربردهای وباسکرپینگ با سیشارپ را نشان میدهد.

پیش نیازهای Web Scraping با C#
در این بخش به معرفی و شرح پیشنیازهایی پرداخته شده است که برای وب اسکریپینگ با سی شارپ مورد نیاز هستند. این موارد در زیربخشهایی جداگانه شامل دانلود و راهاندازی محیط و ابزارهای اولیه و همچنین ایجاد پروژه در سی شارپ، ارائه شده است.
تنظیم و راهاندازی محیط برنامه نویسی وب اسکرپینگ با سی شارپ
به منظور پیادهسازی وب اِسکرِپینگ با سی شارپ، لازم است تا پیش نیازهای زیر را فراهم کنیم:
- دانت نت نسخه ۷ (یا بالاتر): توصیه میشود که از جدیدترین نسخه دانت نت استفاده شود.
- محیط IDE برای کد نویسی C#: ویژوال استدیو کامیونیتی ۲۰۲۲، میتواند گزینه مناسبی برای Web Scraping با سی شارپ باشد. همچنین اگر گزینه کمحجمتری را ترجیح میدهید، میتوانید محیط ویژوال استدیو کد، به همراه افزونه C# را انتخاب کنید.
برای صرفه جویی در زمان، بهتر است بسته دات نت Coding Pack را دانلود و نصب کنید. با نصب این بسته، «ویژوال استودیو کد» (VSCode) به همراه افزونههای ضروری دات نت SDK را خواهید داشت. در غیر این صورت، میتوانید ابزارهای مورد نیاز را به صورت جداگانه، دانلود و نصب کنید.
اکنون، همه چیز برای Web Scraping با سی شارپ آماده است ولی برای اطمینان از اینکه دات نت را به درستی نصب کردهایم، میبایست پنجرهی پاورشل را باز کرده و دستورات زیر را در آن اجرا کنیم.
در صورتی که مشکلی وجود نداشته باشد، شماره نسخه دات نت SDK که روی سیستم نصب شده است، در خروجی چاپ میشود (ما در اینجا نسخه ۷٫۰٫۱۰۱ از دات نت SDK را برای وب اسکرپینگ با سی شارپ نصب کردیم).
در صورتی که بجای دستور بالا، پیغامیبا محتوای زیر نمایش داده شد،
نیاز است که سیستم را ریستارت و مراحل فوق را دوباره امتحان کنیم. در صورت مشاهده مجدد این خطا، بهتر است که دات نت از روی سیستم حذف و دوباره نصب شود.
راه اندازی پروژه سی شارپ
یک «اپلیکیشن کنسول» (Console Application) را در ویژوال استدیو ایجاد میکنیم. به این صورت که ابتدا، یک پوشه خالی به نام SimpleWebScraper ، برای پروژهی Web Scraping با سی شارپ میسازیم.
حالا، VSCode را باز میکنیم و پس از کلیک روی منوی File، گزینه Open Folder را انتخاب میکنیم (معادل کلید ترکیبی Ctrl+K Ctrl O).

در پنجره باز شده، پوشه SimpleWebScraper را انتخاب و صبر میکنیم تا ویژوال استدیو آن را باز کند. سپس با انتخاب گزینه Terminal از منویView که در نوار منوی اصلی وجود دارد، پنجره Terminal را نیز به ویژوال استدیو اضافه میکنیم.

در پنجره Terminal، دستور زیر را اجرا میکنیم:
دستور بالا، یک پروژه کنسول .NET 7.0 را راهاندازی میکند. به بیان دقیقتر، یک فایل پروژه با فرمت .csprojو یک فایل C# به نام Program.csایجاد میشود. حالا، کد زیر را با محتویات موجود در Program.cs، جایگزین میکنیم.
این کد، نمونهای از یک اسکریپت ساده کنسول در سی شارپ است. توجه داشته باشیم که تابع Main()، شامل منطق وب اِسکرِپینگ با سی شارپ خواهد بود. با دستور زیر ، میتوانیم اسکریپت را اجرا کنیم:
که باید خروجی زیر را چاپ کند:
"Hello, World!"بسیار عالی، اسکریپت اولیه C#، همانطوری که انتظار میرفت بدون مشکل کار میکند و ما با خیال راحت میتوانیم مقدمات یادگیری Web Scraping با سی شارپ را ادامه دهیم.
چگونه اطلاعات یک وبسایت را جمع آوری کنیم؟
در این قسمت، وب اسکرپینگ با سی شارپ را در قالب ساخت برنامهای برای استخراج دادهها از وبسایت ScrapeMe یاد میگیریم. وبسایت ScrapeMe، فهرستی از عناصر الهام گرفته از شخصت کارتونی Pokemon را در قالب چندین صفحه به نمایش میگذارد. اسکریپت C#، به طور خودکار، داده مربوط به هر محصول را بازدید و استخراج میکند.
در تصویر زیر، نمایی از وبسایت ScrapeMe، نشان داده شده است.

حالا وقت آن رسیده که برخی از وابستگیها را نصب و استخراج داده از وب را شروع کنیم.
گام اول: نصب کتابخانه Html Agility Pack و افزونه CSS Selector مربوط به آن
Html Agility Pack (که به اختصار HAP هم نامیده میشود)، یکی از کتابخانههای قدرتمند و منبع باز .NET برای تجزیه اسناد HTML است. این کتابخانه که API منعطفی برای وب اِسکرِپینگ محسوب میشود، به ما اجازه میدهد تا صفحه HTML مورد نظر را دانلود و تجزیه کنیم. همچنین میتوانیم عناصر HTML را انتخاب کرده و دادهها را از آنها بیرون بکشیم. کتابخانه Html Agility Pack را از طریق برنامه مدیر بسته NuGet، با استفاده از دستور زیر نصب میکنیم.
با اینکه Html Agility Pack به طور ذاتی از XPath و XSLT پشتیبانی میکند، اما اینها روشهای محبوبی برای انتخاب عناصر HTML از DOM محسوب نمیشوند. خوشبختانه، افزونهای به نام CSS Selector وجود دارد که محبوبیت بیشتری دارد. این افزونه از طریق کتابخانه HtmlAgilityPack.CssSelectors از NuGet قابل نصب است.
با نصب این افزونه، HAP قادر خواهد بود تا سلکتورهای CSS را با روشهای توسعهیافتهای درک کند. سلکتورهای CSS، اولین بخش از یک دستور CSS هستند و به مرورگر میگویند که کدام عناصر از HTML باید انتخاب شوند تا مقادیر ویژگی CSS که در داخل دستور تعیین کردیم، روی آنها اعمال شوند.

حالا میبایست، کتابخانه Html Agility Pack را با افزودن خط زیر در ابتدای فایل Program.cs پروژه، به خزنده وب C#، وارد کنیم.
اگر تا اینجای کار، ویژوال استدیو خطایی را گزارش نکرد، یعنی کار به درستی پیش رفته است.
گام دوم: بارگیری صفحه وب هدف
منظور از «صفحهوب هدف» (Target Web Page)، صفحهای است که قصد اِسکرِپینگ آن را داریم. با ایجاد شیای از Html Agility Pack شروع میکنیم.
HtmlWeb به ما امکان دسترسی به قابلیتهای وب اِسکرِپینگ ارائه شده توسط HAP را میدهد. سپس از متد Load() مربوط به HtmlWeb ، برای دریافت HTML از URL استفاده میکنیم.
در پشت صحنه، HAP یک درخواست HTTP از نوع GET را به منظور دانلود صفحه وب و تجزیه محتوای HTML آن ارسال میکند. در صورت بروز خطا، یک HtmlAgilityPack.HtmlWebException و در صورتی که همه چیز همانطور که انتظار میرود کار کند، یک شیHtmlDocument HAP را ارائه میدهد. حالا آماده هستیم تا از HtmlDocument برای استخراج داده از عناصر HTML استفاده کنیم. اما پیش از آن، اجازه بدهید که کد صفحه هدف را به منظور تعریف یک راهبرد موثر برای انتخاب عناصر HTML بررسی کنیم.
گام سوم: بررسی صفحه هدف
صفحه مورد نظر را برررسی میکنیم تا ببینیم ساختار آن چگونه است. این کار را با تگهای HTML هدف (گرههای مورد نظر) که عناصر محصول را تشکیل میدهند، شروع میکنیم. روی یکی از این تگها راست کلیک و با انتخاب گزینه Inspect به DevTools مرورگر، دسترسی پیدا میکنیم.
لازم به ذکر است که DevTools، بخشی از مرورگر است که ابزارها و امکاناتی را برای برنامه نویسان فراهم میکند.

در اینجا، یک تگ li.productHTML را میبینید که متشکل از چهار مولفه زیر است:
- URL محصول در تگ a
- تصویر محصول در تگ img
- نام محصول در تگ h2
- قیمت محصول در تگ span با کلاس .price
در صورت بررسی سایر محصولات، خواهید دید که آنها نیز از ساختار یکسانی پیروی میکنند. در حقیقت چیزی که تغییر میکند، مقادیر ذخیره شده در پشت عناصر HTML هستند و این یعنی میتوانیم همه آنها را با برنامهنویسی، Scrape کنیم. در ادامه آموزشِ Web Scraping با سی شارپ، چگونگی اِسکرِپ دادهها از این عناصر HTML محصول را با استفاده از ابزار HAP در C#، یاد میگیریم.
گام چهارم: استخراج داده از عناصر HTML
ما باید یک کلاس سفارشی C# را برای ذخیره دادههای Scrape شده تعریف کنیم. برای این منظور، یک کلاس PokemonProduct را به شرح زیر، در داخل Program برنامه خود مینویسیم:
کلاس فوق شامل فیلدهای Url، Image، Name و Price است. این فیلدها، مواردی هستند که قصد Scrape کردن آنها را از هر محصول داریم. حالا، فهرستی از PokemonProduct را در تابع Main() برنامه، مانند خط زیر مقداردهی میکنیم.
عبارت فوق شامل، داده Scrape و ذخیره شده در «وهلههای» (Instances) PokemonProduct است. حالا وقت آن فرا رسیده است تا با استفاده از HAP، فهرستی از همه عناصر HTML li.product را از DOM بیرون بِکشیم، شبیه به کد زیر:
متد QuerySelectorAll()، این امکان را برایمان فراهم میکند تا گرههای HTML را از DOM با استفاده از سلکتور CSS، بازیابی کنیم. در متد فوق، استراتژی سلکتور CSS li.product، برای به دست آوردن تمام عناصر محصول اعمال شده است. به طور خاص،QuerySelectorAll() فهرستی از اشیای HtmlNode HAP را بر میگرداند.
این نکته حائز اهمیت است که متد QuerySelectorAll() به افزونه CSS Selector مربوط به HAP تعلق دارد. بنابراین نمیتوانیم آن را روی رابط اصلی Html Agility Pack پیدا کنیم. از یک حلقه foreach، برای پیمایش روی لیست HTML و داده Scrape شده هر محصول، استفاده میکنیم.
تا اینجای کار توانستیم منطق وب اسکرپینگ با سی شارپ را پیادهسازی کنیم. متد QuerySelector()، سلکتور CSS را در گرههای فرزند HtmlNode، بهمنظور دریافت یکی از آنها، اعمال میکند.
پس از آن، ما ویژگی HTML را از Attributes انتخاب میکنیم و داده آن را با استفاده از Value بیرون میکشیم. هر مقدار را نیز با استفاده از HtmlEntity.DeEntitize() برای جایگزینی با موجودیتهای شناخته شده HTML، پوشش میدهیم. بهتر است دوباره یادآوری شود که QuerySelector()، متعلق به افزونه CSS Selector است و در حالت عادی نمیتوانیم آن را در HAP بیابیم. اکنون زمان آن رسیده است که یاد بگیریم که چگونه دادههای اِسکرِپ شده را در قالبی خوانا، مانند CSV ذخیره کنیم.
گام پنجم: صدور دادههای اِسکرِپ شده در قالب CSV
ما میتوانیم دادههای اِسکرِپ شده را به وسیله توابع داخلی C# به قالب CSV تبدیل کنیم اما کتابخانه CsvHelper، انتخاب مناسبتری برای این کار است.
خوب است که بدانیم، قالب CSV، به ما اجازه میدهد تا دادهها را در قالبی جدول مانند، ذخیره کنیم. CsvHelper کتابخانهای سریع، منعطف و قابل اطمینان از دات نت است که برای خواندن و نوشتن فایلهای CSV مورد استفاده قرار میگیرد. برای نصب این کتابخانه، کافی است بسته ناگتCsvHelper را با دستور زیر به وابستگیهای پروژه خود اضافه کنیم:
با افزودن خط زیر به ابتدای فایل Program.cs ، این کتابخانه را به پروژه خود اضافه میکنیم:
همانطور که در زیر مشاهده میشود، دادههای به دست آمده را به کمک CSVHelper، به یک فایل خروجی CSV تبدیل میکنیم:
در ابتدا، فایل pokemon-products.csv ایجاد میشود. پس از آن، متد WriteRecords() ، تمام رکوردهای محصول را در فایل CSV مینویسد. به لطف ویژگی using در سی شارپ، این اسکریپت به طور خوکار منابع مربوط به اشیا نوشتن را، آزاد میکند. توجه داشته باشید که «سازنده» (Constructor) به یک پارامتر CultureInfo نیاز دارد. این پارامتر، مشخصات قالب بندی، کاراکترهای جداکننده و پایانِ خط را تعیین میکند. InvariantCulture تضمین میکند که همه نرمافزارها میتوانند CSV تولید شده را بدون در نظر گرفتن تنظیمات محلی کاربر، تجزیه کنند.
برای استفاده از مقادیرCultureInfo، نیاز است که دستور زیر را نیز اضافه کنیم.
بسیار عالی. تنها چیزی که باقی میماند، اجرای وب اِسکرِپری است که با سی شارپ نوشتیم.
گام ششم: راهاندازی اِسکرِپر
محتوای فایل Program.cs، در وب اِسکرِپری که تا کنون نوشتیم به صورت زیر است:
با دستور زیر، اسکریپت را اجرا میکنیم:
بسته به زمان پاسخگویی سرور صفحه مورد نظر، ممکن است کمیطول بکشد. پس از پایان این فرایند، میتوانیم فایل pokemon-products.csv را در پوشه اصلی پروژه C# خود، پیدا کنیم. برای بررسی دادهها، آن را باز کنید.

همانطور که دیدیم، با نوشتن حدود 50 خط کُد توانستیم پروژه وب اسکرپینگ با سی شارپ را به طور کاملا کاربردی ایجاد کنیم.
وب اسکرپینگ پیشرفته در سی شارپ
Web Scraping با سی شارپ، فراتر از اصولی است که تاکنون دیدیم. در ادامه، تکنیکهای پیشرفتهتری را یاد خواهیم گرفت تا به ما برای تبدیل شدن به یک متخصص وب اسکرپینگ با سی شارپ، کمک کند.
Web Crawling با دات نت
فراموش نکنیم که وبسایت ScrapeMe، لیستی «صفحهبندی شده» (Pagination) از محصولات را نشان میدهد، به این معنی که وبسایت هدف، از چندین صفحه وب تشکیل شده است. برای اِسکرِپینگ همه محصولات، باید کل وبسایت بازدید شود، این همان چیزی است که «خزیدن در وب» (Web Crawling) به آن اشاره دارد.
برای انجام Web Crawling در سی شارپ، باید تمام لینکهای صفحهبندی را دنبال کنیم. عنصر HTML مربوط به صفحهبندی را بررسی میکنیم با این هدف که بفهمیم چگونه URL صفحات باید استخراج شوند. با راست کلیک روی شماره صفحه، گزینه Inspect را انتخاب میکنیم.

صفحهای مشابه تصویر زیر در DevTools مرورگر، مشاهده میشود.

در اینجا، باید توجه داشت که تمام عناصر HTML مربوط به صفحهبندی، کلاسِ CSS page-numbers (شماره صفحه) را به اشتراک میگذارند. به طور دقیق تر، فقط گرههای HTML شامل URL هستند، در حالی که عناصر span، «نگهدارنده مکان» (Palceholder) محسوب میشوند. بنابراین، میتوانیم تمام عناصر صفحه بندی را با a.page-numbers سلکتور CSS، انتخاب کنیم.
برای جلوگیری از اِسکرِپینگ مجدد یک صفحه، به چند ساختار داده اضافی نیاز داریم:
- pagesDiscovered: لیستی که URLهای پیدا شده به وسیله Crawler را نگه میدارد.
- pagesToScrape: صفی، شامل لیستی از صفحات، که برنامه Crawler به زودی قرار است آنها اِسکرِپ کند.
همچنین به یک متغیرlimit ، که مانع از خزیدن همیشگی برنامه Crawler در صفحات میشود، نیاز داریم.
کارهایی که «خزنده» (Crawler) فوق، انجام میدهد، به شرح زیر است:
- از اولین صفحه در لیست صفحهبندی شروع میکند.
- در صفحه جاری، به دنبال URL-های صفحهبندی جدید میگردد.
- URLهای کشف شده را به صف اِسکرِپینگ اضافه میکند.
- دادهها را از صفحه جاری اِسکرِپ میکند.
- چهار مرحله قبلی را برای هر صفحه موجود در صف، تکرار میکند. این تکرار تا زمانی ادامه مییابد که، یا عناصر وجود در صف تمام شوند (صف خالی شود) یا اینکه به اندازه محدودیت تعیین شده درlimit، از صفحات بازدید کرده باشد.
از آنجایی که وبسایت ScrapeMe از ۴۸ صفحه تشکیل شده است، برای اِسکرِپینگ دادهها از همه محصولات، limit را روی ۴۸ تنظیم میکنیم. در این صورت، pokemon-product.csv ، به ازای هر یک از ۷۵۵ محصول موجود در وبسایت، رکوردی جداگانه خواهد داشت. تا اینجای کار یک برنامه وب اسکرپینگ با سی شارپ ساختهایم که میتواند یک وبسایت را بطور کامل Scrape کند.
پرهیز از بلاک شدن
ممکن است برنامهای که برای Web Scraping با سی شارپ نوشتیم، از کار بیفتد. این اتفاق به دلیل وجود چندین مکانیسم ضد اِسکرِپینگی است که ممکن است وبسایتها اتخاذ کنند. تکنیکهای ضد Scraping زیادی وجود دارند که اسکریپت ما برای مقابله با آنها باید آماده باشد.
ابتداییترین تکنیک، این است که درخواستهای HTTP را بر اساس مقدار «سرآمد» (Headers) آنها مسدود کنیم. این معمولاً زمانی اتفاق میافتد که درخواستها از مقدار User-Agent نامعتبر استفاده میکنند.
سرآمد User-Agent، حاوی اطلاعاتی است که منشأ درخواست را مشخص میکنند. به طور معمول، موارد قابل قبول و معتبر، به مرورگرها و سیستم عاملهای رایج اشاره میکنند. کتابخانههای اِسکرِپینگ تمایل دارند تا از placeholder-هایی از User-Agent استفاده کنند که میتوانند به راحتی برنامه Scraper ما را آشکار کنند. میتوانیم یک User-Agent معتبر را در Html Agility Pack با خط زیر به صورت سراسری ایجاد کنیم.
حالا، اینطور به نظر میرسد که تمام درخواستهای HTTP، که به وسیله HAP انجام شده است، از کروم ۱۰۹ میآیند.
وب اسکرپینگ موازی با سی شارپ
کارایی Web Scraping با سی شارپ، به سرعت وب سرورِ مورد نظر (وب سرور صفحات هدفی که قصد اسکرپ آن را داریم) بستگی دارد. با ایجاد درخواستهای موازی و اِسکرِپینگ صفحات به طور همزمان، با این مشکل مقابله میکنیم. همچنین ضمن پرهیز از اتلاف وقت، سرعت Scraper خود را به سطح بالاتری بهبود میدهیم. این همان مفهومی است که موازیسازی وب اسکرپینگ با سی شارپ، بیان میکند. برای این کار، لیست تمام صفحاتی که Crawler سی شارپی ما باید از آن بازدید کند را در یک ConcurrentBag:ذخیره میکنیم:
Listدر سی شارپ، Thread-Safe نیست و زمانی که صحبت از کارهای موازی میشود، نباید از آن استفاده کنیم. در این مواقع، Listرا با ConcurrentBag، که جایگزینی Thread-Safe و «نامرتب» (non-Order) برای آن است، تعویض میکنیم. Thread-Safe بودن قطعه کد، به این معنی است که نتایج حاصل، به دلیل تعامل همزمان چندین «رشته» (Thread) با کدها، اثرات نامطلوب (دادههای ناسازگار، استثنا و غیره) ایجاد نمیکنند. به همین دلیل، pokemonProducts را به ConcurrentBag تبدیل میکنیم:
بیایید Web Scraping موازی را پیادهسازی کنیم. از Parallel.forEach() برای اجرای یک حلقه foreach به صورت موازی در سی شارپ و همینطور Scraping چندین صفحه به طور همزمان، استفاده میکنیم:
اکنون، برنامهای که برای وب اِسکرِپینگ با سی شارپ نوشتیم، بسیار سریعتر شده است. اما فراموش نکنیم که سطح موازیسازی را برای پرهیز از فشار زیاد به سرور، محدود کنیم. زیرا هدف ما استخراج دادهها از وبسایت و نه انجام یک حمله DoS است. کدهای بالا به عنوان مثالی برای درک چگونگی دستیابی به «Crawling موازی» در سی شارپ بودند. تمام کدهای برنامه Scraping موازی که با سی شارپ نوشتیم را در زیر مشاهده میکنید.
Scraping وبسایت داینامیک با استفاده از مرورگر هِدلِس در سی شارپ
سایتهایی که محتوای استاتیک دارند، تمام محتوای خود را در صفحاتی از HTML جای دادهاند که توسط سرور بازگردانده شدهاست. این موضوع باعث میشود که سایتهای مذکور، به یک هدفِ آسان برای اِسکرِیپینگ، بهوسیله هر کتابخانه تجزیه HTML، تبدیل شوند.
وبسایتهای پویا، از زبان جاوا اسکریپت برای رِندر یا بازیابی دادهها استفاده میکنند. دلیل آن این است که این نوع وبسایتها برای بازیابی داینامیکِ تمام یا بخشی از محتوا به جاوا اسکریپت متکی هستند. اِسکرِپینگ چنین وبسایتهایی نیازمند ابزاری است که بتواند جاوا اسکریپت را مانند یک «مرورگر هِدلِس یا بیسر» (Headless Browser) اجرا کند.
اگر با این اصطلاح آشنا نیستید، باید بگوییم که مرورگر هِدلِس، مرورگری قابل برنامهنویسی و بدون «رابط کاربری گرافیکی» (GUI) است. پُر استفادهترین کتابخانه برای مرورگر هِدلِس در سی شارپ، با بیش از 65 میلیون دانلود، «سلنیوم» (Selenium) نام دارد. برای استفاده از آن، بسته ناگت Selenium.WebDriver را طبق دستور زیر نصب میکنیم:
از سلنیوم در حالت هِدلِس برای اِسکرِپینگ دادهها از وبسایت ScrapeMe، با منطق زیر استفاده میکنیم:
تابع FindElements() سلنیوم، به مرورگر، این امکان را میدهد تا گرههای HTML را جستجو کند. به لطف وجود این تابع، میتوانیم عناصر HTML محصول را از طریق پرس و جوی سلکتورِ CSS، انتخاب و پس از آن، عملیات پیمایش را روی آنها با یک حلقه foreach انجام دهیم. سپس متدGetAttribute() را اِعمال و از Text برای استخراج دادههای مورد نظر استفاده میکنیم.
Web Scraping با سی شارپ، چه از طریق HAP انجام و چه با سلنیوم پیادهسازی شود، کدنویسی تقریباً یکسانی دارد و تفاوت آن، در نحوه اجرای منطق اِسکرِپینگ است. HAP، صفحات HTML را به منظور استخراج دادهها از آن تجزیه میکند و سلنیوم دستورات اِسکرِپینگ را در یک مرورگر هِدلِس اجرا میکند.

به لطف وجود سلنیوم، میتوانیم وبسایتهایی با محتوای پویا را Crawl کنیم و مانند یک کاربر واقعی در مرورگر، با صفحات وب، تعامل داشته باشیم. همچنین کُد ما احتمالاً به عنوان یک ربات شناسایی میشود. در نتیجه، با استفاده از سلنیوم، Scraping صفحه وب با پرهیز از انسداد، آسانتر میشود.
بسته Html Agility Pack، تمامیقابلیتهای مرورگر را به همراه ندارد، بنابراین، از HAP فقط میتوانیم به منظور اِسکرِیپینگِ وبسایتهای ایستا استفاده کنیم. همچنین مانند سلنیوم، سربار اضافی منابع، برای اجرای یک مرورگر معمولی را به همراه ندارد.
کد نهایی Web Scraping با سی شارپ
در این بخش، کد کامل Web Scraping با سی شارپ، به همراه Crawling و منطق ضدبلاک اولیه، که با استفاده از بسته Html Agility Pack ساختیم، ارائه شده است.
در نتیجه، با نوشتن کمتر از 100 خط کد توانستیم، برنامه Web Scraping با سی شارپ را پیادهسازی کنیم.

سایر کتابخانه های وب اسکرپینگ با سی شارپ کدامند؟
در این بخش، ابزارهای دیگری که در Web Scraping با سی شارپ میتوانند مورد استفاده قرار بگیرند، به شرح زیر معرفی شده است:
- ZenRows: یک API با امکانات فراوان و قابلیت استفاده آسان برای تسهیل فرایند استخراج دادهها از صفحات وب است. ZenRows میانبُری خودکار برای هر سیستم ضد ربات یا ضد اِسکرِپینگ فراهم میکند. علاوه بر این، به همراه پراکسی، مرورگر هِدلِس کاربردی و تضمین آپتایم ۹۹ درصدی ارائه میشود.
- Puppeteer Sharp: کتابخانه الهام گرفته شده دات نت از Puppeteer در Node.js است. با استفاده از آن، میتوانیم یک مرورگر کرومیوم هِدلِس را به منظور تست و اِسکرِپینگ هدایت کنیم.
- AngleSharp: کتابخانه اپن سورسی از دات نت، با هدف تجزیه و دستکاری اسناد XML و HTML است. این کتابخانه به ما امکان میدهد تا دادهها را از یک وبسایت استخراج و عناصر HTML را از طریق سلکتورهای CSS، انتخاب کنیم.
- HttpClient: محبوبترین کلاینت HTTP سی شارپ است و در زمینه وب اسکرپینگ نیز کاربرد دارد. زیرا به شما امکان میدهد درخواستهای HTTP را به راحتی و به صورت «ناهمزمان» (Asynchronously) انجام دهید.

جمعبندی
در این نوشتار، اطلاعات مربوط به یادگیری وب اسکرپینگ با سی شارپ تا حد زیادی پوشش و آموزش داده شد. ابتدا اصول و مفاهیم اولیه Web Scraping را یاد گرفتیم، سپس کار را با پیادهسازی مفاهیم پیشرفته Web Scraping با سی شارپ ادامه دادیم.
به طور خلاصه، اکنون میدانیم:
- چگونه با استفاده از بسته Html Agility Pack، اِسکرِپینگ مقدماتی وب را در سی شارپ انجام دهیم.
- چگونه کل یک وبسایت را از طریق خزیدن در وب Scrape کنیم.
- در مواقع مورد نیاز، از راهحلی که مرورگر هِدلِس سی شارپ ارائه میدهد استفاده کنیم.
- چگونه دادههای وبسایت پویا را با استفاده از سلنیوم استخراج کنیم.
Web Scraping با سی شارپ، چالشی نسبتاً بزرگ به حساب میآید. زیرا در حال حاضر، وبسایتها از فناوریهای ضد Scraping زیادی استفاده میکنند. دور زدن همه آنها کار آسانی نیست و ما همیشه باید به دنبال راه حلی برای این چالش باشیم. در این مسیر میتوانیم از APIهای موجود نیز، استفاده کنیم.
سوالات متداول Web Scraping با سی شارپ
در این بخش به تعدادی از پرسشهای رایج پیرامون وب اسکریپینگ در سی شارپ پاسخ داده شده است.
آیا زبان سی شارپ برای وب اسکرپینگ گزینه مناسبی است؟
بله، سی شارپ یک زبان برنامهنویسی همه منظوره است که شما را قادر میسازد تا فرایند وب اسکرپینگ را در حد خیلی خوبی انجام دهید. سی شارپ دارای یک کامیونیتی بزرگ و فعال است که کتابخانههای زیادی را برای کمک به شما، در دستیابی به هدفی که از وب اسکرپینگ دارید، توسعه داده است.
وب اسکرپینگ با سی شارپ چگونه انجام می شود؟
وب اسکرپینگ در سی شارپ، مانند سایر زبانهای برنامه نویسی انجام میشود. با استفاده از یک کتابخانه سی شارپ مربوط به وب اسکرپینگ، میتوانید به وبسایت مورد نظر متصل شوید، عناصر HTML را از DOM آن انتخاب و دادههای آن را بازیابی کنید.
بهترین روش برای وب اسکرپینگ با سی شارپ چیست؟
استفاده از کتابخانههای موجود در NuGet برای Scraping در سی شارپ، همه چیز را آسانتر میکند. Selenium ،ScrapySharp و Html Agility Pack، برخی از محبوبترین کتابخانههای سی شارپ برای استفاده در پروژههای اسکرپینگ دادهها محسوب میشوند.
با دادههای Scrape شده چه باید کرد؟
پس از جمعآوری دادهها، با توجه به هدفی که در ذهن داریم، لازم است آنها را در جایی نگهداری کنیم. در ادامه برخی از این موارد فهرست شدهاند.
- آنها را میتوان در پایگاهداده ذخیره کرد تا هر جایی که نیاز شد، با پرس و جو بازیابی شوند.
- آنها را به قالب JSON تبدیل کنیم و از آن برای فراخوانی برخی از APIها کمک بگیریم.
- تبدیل دادههای Scrape شده به فرمتهای قابل خواندن برای افراد دیگر، در قالبهایی مانند CSV، که با مایکروسافت اکسل نیز قابل نمایش است.
این روشها، فقط چندین نمونه رایج هستند. اما نکته مهم، این است که وقتی دادههای Scrape شده را در کدهایتان دارید، میتوانید آنها را به هر نحوی که مایل بودید، استفاده کنید. به طور معمول، دادههای Scrape شده به قالب مفیدتری برای بازاریابی، تجزیه و تحلیل دادهها یا تیم فروش شما تبدیل میشوند.
حریم خصوصی در Web Scraping با سی شارپ چگونه حفظ میشود؟
اگر میخواهید از مواردی همچون، افشای آدرس IP، مسدود شدن و افشای هویت خودتان جلوگیری کنید، پروکسیهای وب اسکرپینگ، این کار را برای شما انجام میدهند. پروکسی سرور، به عنوان دروازهای بین برنامه شما و سرور وبسایت مورد نظر عمل میکند و در نتیجه IP شما پنهان میشود. به این ترتیب، این سرویس به شما کمک میکند تا بر مشکل انسداد IP غلبه کنید و همچنین، دادهها را به صورت ناشناس Scrape و محتوای مورد نظر را در همه کشورها باز کنید. پروکسیها انواع مختلفی دارند و در مقاصد متنوعی استفاده میشوند. بنابراین باید مطمئن شوید که پروکسی سرور مناسبی را انتخاب میکنید.












