آموزش ساخت crawler
نویسنده : سمانه KZ | زمان انتشار : 05 آذر 1399 ساعت 18:36
تعداد بازدید ها: 4,134
آیا تا به حال قصد داشتهاید اطلاعات خاصی از یک وبسایت برای پردازش بیشتر به دست آورید؟ برای مثال اطلاعاتی شبیه امتیازات مسابقات ورزشی، روند بازار سهام، بیت کوین و دیگر قیمتهای ارز دیجیتال را در نظر بگیرید. اگر اطلاعاتی که نیاز دارید در وبسایتی موجود است، میتوانید یک «خزنده» (crawler) – بهعنوان یک «scraper» یا عنکبوت نیز شناخته میشود – بنویسید تا وبسایت را پیمایش و تنها آنچه را که لازم دارید استخراج کنید. بیایید یاد بگیریم با پایتون چگونه این کار را انجام دهیم.
لطفا توجه داشته باشید که وبسایتهای گوناگونی استفاده از خزنده را برای دسترسی به اطلاعاتی که فراهم میکند، مجاز نمیدانند. پس قبل از ایجاد و فعال کردن یک خزنده روی سایتی معین، ابتدا قوانین و شرایط بهرهگیری از آن سایت را بررسی کنید.
نصب Scrapy
برای مدیریت خزنده واقعی از ماژولی در پایتون به نام «Scrapy» استفاده میکنیم. این کار سریع و ساده است و میتواند چندین صفحه وب را دقیقا مانند آنچه با یک مرورگر انجام میدهید، مرور کند. توجه داشته باشید با این حال، Scrapy هیچ امکاناتی برای پردازش جاوا اسکریپت هنگام مرور وبسایت ندارد. بنابراین وبسایتها و برنامههایی که از جاوا اسکریپت برای تنظیم رابط کاربری خود استفاده میکنند، نمیتوانند در این روش بهدرستی مورد استفاده قرار گیرند.
حال نوبت به نصب scrapy میرسد و برای این منظور از «virtualenv» کمک میگیریم. بهرهگیری از این شیوه، سبب میشود scrapy در دایرکتوری جداگانه نصب شده و تاثیری نیز بر سایر ماژولهایی که هماکنون روی سیستم نصب هستند نداشته باشد.
در نخستین گام یک دایرکتوری ایجاد و یک محیط مجازی را در آن دایرکتوری راهاندازی کنید.
mkdir crawler cd crawler virtualenv venv .venv/bin/activate |
حال میتوانید Scrapy را در آن دایرکتوری نصب نمایید.
مطمئن شوید که Scrapy بهدرستی نصب شده است.
1 2 3 4 5 6 7 8 9 10 11 12 13 | scrapy # prints Scrapy1.4.0-no active project Usage: scrapy<command>[options][args] Available commands: bench Run quick benchmark test fetch FetchaURL using the Scrapy downloader genspider Generate newspider using pre-defined templates runspider Runaself-contained spider(without creatingaproject) ... |
ساخت یک خزنده وبسایت (عنکبوت)
هدف این است که یک خزنده برای بارگیری اطلاعات نوشته شود. با scraping برای گرفتن برخی اطلاعات از یک صفحه ویکیپدیا در مورد باتری شروع میکنیم. صفحهی زیر را در نظر بگیرید.
https://en.wikipedia.org/wiki/Battery_(electricity).
اولین گام در نوشتن یک خزنده، تعریف یک کلاس پایتون توسعه یافته از scrapy.Spider است. اجازه دهید این کلاس را «spider1» نامگذاری کنیم.
حداقل چیزهایی که یک کلاس Spider نیاز دارد به شرح زیر است:
- نامی برای شناسایی spider، در این مورد «ویکیپدیا» گزینهی مناسبی به نظر میرسد.
- متغیر start_urls حاوی یک فهرست از URL برای شروع خزیدن است. در اینجا از وبسایت ویکیپدیا نشان داده شده برای اولین خزیدن استفاده میشود.
- یک متد ()parse برای پردازش صفحه وب و پیدا کردن آنچه میخواهیم از آن استخراج کنیم.
importscrapy classspider1(scrapy.Spider): name='Wikipedia' start_urls=['https://en.wikipedia.org/wiki/Battery_(electricity)'] defparse(self,response): pass |
اکنون میتوانیم این عنکبوت را اجرا کنیم تا اطمینان حاصل شود که همهچیز درست کار میکند. کد مربوطه به شرح زیر اجرا میشود:
scrapy runspider spider1.py # prints 2017-11-2309:09:21[scrapy.utils.log]INFO:Scrapy1.4.0started(bot:scrapybot) 2017-11-2309:09:21[scrapy.utils.log]INFO:Overridden settings:{'SPIDER_LOADER_WARN_ONLY':True} 2017-11-2309:09:21[scrapy.middleware]INFO:Enabled extensions: ['scrapy.extensions.memusage.MemoryUsage', 'scrapy.extensions.logstats.LogStats', ... |
غیرفعال کردن Logging
همانطور که میبینید، اجرای scrapy با کلاس مینیمال و ابتدایی که ایجاد کردیم، باعث ایجاد گروهی از خروجیها میشود که مفهوم خاصی را به ما نشان نمیدهند. اجازه دهید سطح logging را به «هشدار و تلاش دوباره» (warning and retry) تغییر دهیم؛ خطوط زیر را به ابتدای فایل اضافه کنید.
importlogging logging.getLogger('scrapy').setLevel(logging.WARNING) |
در هنگام اجرای دوباره عنکبوت، باید یک پیغام لاگ حداقلی را مشاهده کنیم.
استفاده از «Chrome Inspector»
استخراج اطلاعات از یک صفحه وب شامل تعیین موقعیت عنصر HTML است که از آن اطلاعات میخواهیم. روش خوب و آسان برای یافتن موقعیت یک عنصر HTML در مرورگر کروم، استفاده از ابزار Inspector است.
- به صفحه مورد نظر در کروم بروید.
- موس را روی عنصری قرار دهید که اطلاعات را از آن میخواهید.
- راست کلیک کنید تا منویی برای شما باز شود.
- Inspect را از منو انتخاب کنید.
این کار باید کنسول توسعهدهنده را با «زبانه» (tab) عناصر انتخاب شده باز کند. پایین زبانه، باید نوار ابزار وضعیت را با موقعیت عنصر نشان داده شده بهصورت زیر ببینید:
html body div#content.mw-body h1#firstHeading.firstHeading.
همانطور که در اینجا توضیح داده میشود، به برخی یا همه بخشهای این قسمت نیاز دارید.
استخراج عنوان
حالا اجازه دهید یک کد با متد ()parse برای استخراج عنوان صفحه اضافه کنیم.
... defparse(self,response): printresponse.css('h1#firstHeading::text').extract() ... |
آرگومان «پاسخ» (Response) یک متد با نام ()css را پشتیبانی میکند که میتواند عناصر HTML صفحه را بر اساس موقعیت تعیین شده آنها انتخاب کند. برای این مورد، عنصر مورد نظر h1.firstHeading است و به متن آن نیاز داریم؛ بنابراین text:: را به آیتمهای انتخابی اضافه میکنیم. درنهایت، متد ()extract عنصر انتخابی را باز میگرداند.
در هنگام اجرای دوبارهی scrapy در این کلاس، خروجی زیر دریافت میشود:
[u'Battery (electricity)'] |
که نشان میدهد عنوان از یک فهرست از رشتههای «Unicode» استخراج شده است.
توصیف (Description) چگونه است؟
برای نشان دادن جنبههای بیشتری از استخراج دادهها از صفحات وب، اجازه دهید اولین پاراگراف توصیفات را از صفحه ویکیپدیای بالا دریافت کنیم. در inspection با استفاده از کنسول توسعهدهنده کروم، میبینیم که مکان عنصر بهصورت زیر است:
div#mw-content-text>div>p
این موقعیت تمام عناصر P که همهی توضیحات را شامل میشوند، بازمیگرداند. از آنجایی که فقط عنصر p را میخواهیم، از استخراج کننده زیر استفاده میکنیم:
response.css('div#mw-content-text>div>p')[0] |
برای استخراج محتوای متن به صورت جداگانه، CSS extractor ::text را اضافه مینماییم:
response.css('div#mw-content-text>div>p')[0].css('::text') |
عبارت نهایی از ()extract که یک فهرست از رشتههای Unicode را بازمیگرداند استفاده میکند. از تابع ()join پایتون برای پیوست فهرست استفاده میکنیم.
defparse(self,response): print''.join(response.css('div#mw-content-text>div>p')[0].css('::text').extract()) |
خروجی در حال اجرای Scrapy به همراه این کلاس همان چیزی است که به دنبال آن هستیم:
An electric battery isadeviceconsisting of one ormore electrochemical cells withexternal connections provided to power electrical devices such asflashlights,smartphones,andelectric cars.[1]Whenabattery issupplying electric power,its positive terminal is ... |
جمعآوری دادهها با استفاده از «yield»
کد بالا دادههای استخراجشده را به کنسول میدهد. هنگامی که نیاز به جمعآوری دادهها در «JSON» دارید، میتوانید از دستورالعمل yield استفاده کنید. نحوه عملکرد yield به شرح زیر است:
اجرای یک تابع که حاوی دستورالعمل yield است و «generator» را به «caller» برمیگرداند. Generator یک تابع است که caller میتواند بهطور مکرر آن را اجرا کند تا پایان یابد. در این قسمت کد مورد نظر، مشابه بالاست که از دستورالعمل yield برای بازگردانی فهرست عناصر p در HTML استفاده میکند.
... defparse(self,response): foreinresponse.css('div#mw-content-text>div>p'): yield{'para':''.join(e.css('::text').extract()).strip()} ... |
اکنون میتوانید عنکبوت را با مشخص کردن یک فایل خروجی JSON بهصورت زیر به کار ببرید:
scrapy runspider spider3.py-ojoe.json |
خروجی تولیدشده به شرح زیر است:
[ {"para":"An 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 the cathode and its negative terminal is the anode.[2] The terminal marked negative is the source of electrons that when connected to an external circuit will flow and deliver energy to an external device. When a battery is connected to an external circuit, electrolytes are able to move as ions within, allowing the chemical reactions to be completed at the separate terminals and so deliver energy to the external circuit. It is the movement of those ions within the battery which allows current to flow out of the battery to perform work.[3] Historically the term \"battery\" specifically referred to a device composed of multiple cells, however the usage has evolved additionally to include devices composed of a single cell.[4]"}, {"para":"Primary(single-useor\"disposable\")batteries are used once anddiscarded;the electrode materials are irreversibly changed during discharge.Common examples are the alkaline battery used forflashlights andamultitude of portable electronic devices.Secondary(rechargeable)batteries can be discharged andrecharged multiple ... |
پردازش چندین بیت اطلاعات
اکنون قصد داریم به استخراج چندین بیت مرتبط با اطلاعات نگاه کنیم. برای این مثال، بهترین عناوین «IMDb Box Office» را برای آخر هفته به دست میآوریم. این اطلاعات در آدرس زیر در دسترس هستند:
http://www.imdb.com/chart/boxoffice
با استفاده از متد ()parse فیلدهای مختلف را در هر سطر استخراج میکنیم. همانطور که در بالا توضیح داده شد، مجددا مکانهای عنصر CSS با استفاده از کنسول توسعهدهنده کروم، تعیین میشوند:
... defparse(self,response): foreinresponse.css('div#boxoffice>table>tbody>tr'): yield{ 'title':''.join(e.css('td.titleColumn>a::text').extract()).strip(), 'weekend':''.join(e.css('td.ratingColumn')[0].css('::text').extract()).strip(), 'gross':''.join(e.css('td.ratingColumn')[1].css('span.secondaryInfo::text').extract()).strip(), 'weeks':''.join(e.css('td.weeksColumn::text').extract()).strip(), 'image':e.css('td.posterColumn img::attr(src)').extract_first(), } ... |
توجه داشته باشید که انتخابگر تصویر بالا مشخص میکند که img زیر ردهی td.posterColumn است. باید ویژگی src را با استفاده از عبارت (atr(src:: استخراج کنیم. اجرای عنکبوت، JSON زیر را برمیگرداند:
[ {"gross":"$93.8M","weeks":"1","weekend":"$93.8M","image":"https://images-na.ssl-images-amazon.com/images/M/MV5BYWVhZjZkYTItOGIwYS00NmRkLWJlYjctMWM0ZjFmMDU4ZjEzXkEyXkFqcGdeQXVyMTMxODk2OTU@._V1_UY67_CR0,0,45,67_AL_.jpg","title":"Justice League"}, {"gross":"$27.5M","weeks":"1","weekend":"$27.5M","image":"https://images-na.ssl-images-amazon.com/images/M/MV5BYjFhOWY0OTgtNDkzMC00YWJkLTk1NGEtYWUxNjhmMmQ5ZjYyXkEyXkFqcGdeQXVyMjMxOTE0ODA@._V1_UX45_CR0,0,45,67_AL_.jpg","title":"Wonder"}, {"gross":"$247.3M","weeks":"3","weekend":"$21.7M","image":"https://images-na.ssl-images-amazon.com/images/M/MV5BMjMyNDkzMzI1OF5BMl5BanBnXkFtZTgwODcxODg5MjI@._V1_UY67_CR0,0,45,67_AL_.jpg","title":"Thor: Ragnarok"}, ... ] |
چنین مطالبی را میتوانید در لینکهای زیر دنبال کنید.
- آموزش طراحی وب با HTML – مقدماتی
- آموزش طراحی وب با HTML – تکمیلی
- HTML و هر آنچه باید پیش از شروع یادگیری آن بدانید — راهنمای مقدماتی و کاربردی
- آموزش برنامه نویسی پایتون
- آموزش تکمیلی برنامه نویسی پایتون
^^
بر اساس رای 5 نفر
آیا این مطلب برای شما مفید بود؟