چگونه یک «خزنده وب» (Web Crawler) بسیار ابتدایی بسازیم؟
آیا تا به حال قصد داشتهاید اطلاعات خاصی از یک وبسایت برای پردازش بیشتر به دست آورید؟ برای مثال اطلاعاتی شبیه امتیازات مسابقات ورزشی، روند بازار سهام، بیت کوین و دیگر قیمتهای ارز دیجیتال را در نظر بگیرید. اگر اطلاعاتی که نیاز دارید در وبسایتی موجود است، میتوانید یک «خزنده» (crawler) - بهعنوان یک «scraper» یا عنکبوت نیز شناخته میشود - بنویسید تا وبسایت را پیمایش و تنها آنچه را که لازم دارید استخراج کنید. بیایید یاد بگیریم با پایتون چگونه این کار را انجام دهیم.
لطفا توجه داشته باشید که وبسایتهای گوناگونی استفاده از خزنده را برای دسترسی به اطلاعاتی که فراهم میکند، مجاز نمیدانند. پس قبل از ایجاد و فعال کردن یک خزنده روی سایتی معین، ابتدا قوانین و شرایط بهرهگیری از آن سایت را بررسی کنید.
نصب Scrapy
برای مدیریت خزنده واقعی از ماژولی در پایتون به نام «Scrapy» استفاده میکنیم. این کار سریع و ساده است و میتواند چندین صفحه وب را دقیقا مانند آنچه با یک مرورگر انجام میدهید، مرور کند. توجه داشته باشید با این حال، Scrapy هیچ امکاناتی برای پردازش جاوا اسکریپت هنگام مرور وبسایت ندارد. بنابراین وبسایتها و برنامههایی که از جاوا اسکریپت برای تنظیم رابط کاربری خود استفاده میکنند، نمیتوانند در این روش بهدرستی مورد استفاده قرار گیرند.
حال نوبت به نصب scrapy میرسد و برای این منظور از «virtualenv» کمک میگیریم. بهرهگیری از این شیوه، سبب میشود scrapy در دایرکتوری جداگانه نصب شده و تاثیری نیز بر سایر ماژولهایی که هماکنون روی سیستم نصب هستند نداشته باشد.
در نخستین گام یک دایرکتوری ایجاد و یک محیط مجازی را در آن دایرکتوری راهاندازی کنید.
1mkdir crawler
2cd crawler
3virtualenv venv
4. venv/bin/activate
حال میتوانید Scrapy را در آن دایرکتوری نصب نمایید.
1pip install scrapy
مطمئن شوید که Scrapy بهدرستی نصب شده است.
1scrapy
2# prints
3Scrapy 1.4.0 - no active project
4
5Usage:
6 scrapy <command> [options] [args]
7
8Available commands:
9 bench Run quick benchmark test
10 fetch Fetch a URL using the Scrapy downloader
11 genspider Generate new spider using pre-defined templates
12 runspider Run a self-contained spider (without creating a project)
13...
ساخت یک خزنده وبسایت (عنکبوت)
هدف این است که یک خزنده برای بارگیری اطلاعات نوشته شود. با scraping برای گرفتن برخی اطلاعات از یک صفحه ویکیپدیا در مورد باتری شروع میکنیم. صفحهی زیر را در نظر بگیرید.
https://en.wikipedia.org/wiki/Battery_(electricity).
اولین گام در نوشتن یک خزنده، تعریف یک کلاس پایتون توسعه یافته از scrapy.Spider است. اجازه دهید این کلاس را «spider1» نامگذاری کنیم.
حداقل چیزهایی که یک کلاس Spider نیاز دارد به شرح زیر است:
- نامی برای شناسایی spider، در این مورد «ویکیپدیا» گزینهی مناسبی به نظر میرسد.
- متغیر start_urls حاوی یک فهرست از URL برای شروع خزیدن است. در اینجا از وبسایت ویکیپدیا نشان داده شده برای اولین خزیدن استفاده میشود.
- یک متد ()parse برای پردازش صفحه وب و پیدا کردن آنچه میخواهیم از آن استخراج کنیم.
1import scrapy
2
3class spider1(scrapy.Spider):
4 name = 'Wikipedia'
5 start_urls = ['https://en.wikipedia.org/wiki/Battery_(electricity)']
6
7 def parse(self, response):
8 pass
اکنون میتوانیم این عنکبوت را اجرا کنیم تا اطمینان حاصل شود که همهچیز درست کار میکند. کد مربوطه به شرح زیر اجرا میشود:
scrapy runspider spider1.py # prints 2017-11-23 09:09:21 [scrapy.utils.log] INFO: Scrapy 1.4.0 started (bot: scrapybot) 2017-11-23 09:09:21 [scrapy.utils.log] INFO: Overridden settings: {'SPIDER_LOADER_WARN_ONLY': True} 2017-11-23 09:09:21 [scrapy.middleware] INFO: Enabled extensions: ['scrapy.extensions.memusage.MemoryUsage', 'scrapy.extensions.logstats.LogStats', ...
غیرفعال کردن Logging
همانطور که میبینید، اجرای scrapy با کلاس مینیمال و ابتدایی که ایجاد کردیم، باعث ایجاد گروهی از خروجیها میشود که مفهوم خاصی را به ما نشان نمیدهند. اجازه دهید سطح logging را به «هشدار و تلاش دوباره» (warning and retry) تغییر دهیم؛ خطوط زیر را به ابتدای فایل اضافه کنید.
1import logging
2logging.getLogger('scrapy').setLevel(logging.WARNING)
در هنگام اجرای دوباره عنکبوت، باید یک پیغام لاگ حداقلی را مشاهده کنیم.
استفاده از «Chrome Inspector»
استخراج اطلاعات از یک صفحه وب شامل تعیین موقعیت عنصر HTML است که از آن اطلاعات میخواهیم. روش خوب و آسان برای یافتن موقعیت یک عنصر HTML در مرورگر کروم، استفاده از ابزار Inspector است.
- به صفحه مورد نظر در کروم بروید.
- موس را روی عنصری قرار دهید که اطلاعات را از آن میخواهید.
- راست کلیک کنید تا منویی برای شما باز شود.
- Inspect را از منو انتخاب کنید.
این کار باید کنسول توسعهدهنده را با «زبانه» (tab) عناصر انتخاب شده باز کند. پایین زبانه، باید نوار ابزار وضعیت را با موقعیت عنصر نشان داده شده بهصورت زیر ببینید:
html body div#content.mw-body h1#firstHeading.firstHeading.
همانطور که در اینجا توضیح داده میشود، به برخی یا همه بخشهای این قسمت نیاز دارید.
استخراج عنوان
حالا اجازه دهید یک کد با متد ()parse برای استخراج عنوان صفحه اضافه کنیم.
1...
2 def parse(self, response):
3 print response.css('h1#firstHeading::text').extract()
4...
آرگومان «پاسخ» (Response) یک متد با نام ()css را پشتیبانی میکند که میتواند عناصر HTML صفحه را بر اساس موقعیت تعیین شده آنها انتخاب کند. برای این مورد، عنصر مورد نظر h1.firstHeading است و به متن آن نیاز داریم؛ بنابراین text:: را به آیتمهای انتخابی اضافه میکنیم. درنهایت، متد ()extract عنصر انتخابی را باز میگرداند.
در هنگام اجرای دوبارهی scrapy در این کلاس، خروجی زیر دریافت میشود:
1[u'Battery (electricity)']
که نشان میدهد عنوان از یک فهرست از رشتههای «Unicode» استخراج شده است.
توصیف (Description) چگونه است؟
برای نشان دادن جنبههای بیشتری از استخراج دادهها از صفحات وب، اجازه دهید اولین پاراگراف توصیفات را از صفحه ویکیپدیای بالا دریافت کنیم. در inspection با استفاده از کنسول توسعهدهنده کروم، میبینیم که مکان عنصر بهصورت زیر است:
div#mw-content-text>div>p
این موقعیت تمام عناصر P که همهی توضیحات را شامل میشوند، بازمیگرداند. از آنجایی که فقط عنصر p را میخواهیم، از استخراج کننده زیر استفاده میکنیم:
1response.css('div#mw-content-text>div>p')[0]
برای استخراج محتوای متن به صورت جداگانه، CSS extractor ::text را اضافه مینماییم:
1response.css('div#mw-content-text>div>p')[0].css('::text')
عبارت نهایی از ()extract که یک فهرست از رشتههای Unicode را بازمیگرداند استفاده میکند. از تابع ()join پایتون برای پیوست فهرست استفاده میکنیم.
1 def parse(self, response):
2 print ''.join(response.css('div#mw-content-text>div>p')[0].css('::text').extract())
خروجی در حال اجرای Scrapy به همراه این کلاس همان چیزی است که به دنبال آن هستیم:
1An electric battery is a device consisting of one or more electrochemical cells with external connections provided to power electrical devices such as flashlights, smartphones, and electric cars.[1] When a battery is supplying electric power, its positive terminal is
2...
جمعآوری دادهها با استفاده از «yield»
کد بالا دادههای استخراجشده را به کنسول میدهد. هنگامی که نیاز به جمعآوری دادهها در «JSON» دارید، میتوانید از دستورالعمل yield استفاده کنید. نحوه عملکرد yield به شرح زیر است:
سلام با تشکر از مطالب عالی سایتتون
ایا میشه تعداد بازدید کننده ها رو با وب اسکرپینگ (Web Scraping) با پایتون و کتابخانه Beautiful Soup انجام داد (البته برای هر سایتی نه برای سایت خودمان )