ایجاد عنکبوت را در Scrapy با Jinja2 و JSON به صورت خودکار انجام دهید

Summarize this content to 400 words in Persian Lang
امروز، من قصد دارم در مورد اتوماسیون حذف وب خود که اخیراً در حال کار هستم و قصد دارم تاریخ را از هزاران وب سایت حذف کنم، به اشتراک بگذارم. بله، کار بر روی یک پروژه خراش دادن در مقیاس بزرگ.
مسئله :شما یک پروژه خراش داده جدید دریافت کردید که شامل خراش دادن داده ها از بسیاری از وب سایت های مشابه است. به عنوان مثال، دادههای مربوط به کتابها از وبسایتهای مرتبط با کتابهای مختلف. یا اطلاعات شکلاتی از منابع بسیاری.
ممکن است فکر کنید، مشکل اینجا چیست، می توان با استفاده از آن انجام داد خراشیده یا هر ابزار یا فریمورک مشابه دیگری! این مانند هر پروژه معمولی خراش دادن داده است اما صبر کنید! اگر منابع از 100 یا 1000 باشد چه! آیا هنوز هم استفاده می کنید “scrapy genspider 1000 بار و سپس به ویرایش و تغییر هر عنکبوت یکی پس از دیگری؟
راه حل :
پروژه اسکرپی خط پایه خود را ایجاد کنید که دارای 1-2 عنکبوت با تمام اجزای دیگر مانند آیتم ها، آیتم لودر، خط لوله، میان افزارها و تنظیمات مناسب باشد و سپس یک اسکریپت اتوماسیون ایجاد عنکبوت بنویسید که دارای یک فایل قالب (بر اساس 1-2 عنکبوت شما) خواهد بود. یک فایل json دارای جزئیات منبع و انتخابگر برای هر آیتم (در هر منبع). هنگامی که اسکریپت را اجرا می کنید، عنکبوت برای همه منابع موجود ایجاد می شود.
مراحل:
مراحل بسیار ساده خواهند بود، همانطور که به طور انتزاعی در بخش حل ذکر شد. بیایید یک لیست کوتاه در اینجا (از جمله ایجاد محیط مجازی) داشته باشیم:
ایجاد یک محیط مجازی برای پایتون (Conda یا venv)
اسکراپی را نصب کنید
یک پروژه خراب ایجاد کنید
اولین عنکبوت ساده را برای یک منبع ایجاد کنید
اجزای دیگر مانند آیتم ها، آیتم لودر، خطوط لوله و غیره را تست و ایجاد کنید.
هنگامی که پروژه خراش دادن شما با 1-2 عنکبوت و سایر اجزا آماده شد. اکنون به سمت اتوماسیون ایجاد عنکبوت بروید (نه فرآیند خراش دادن)
یک فایل json ایجاد کنید که در آن هر یک از ویژگی های مورد (به عنوان مثال: عنوان، نویسنده، قیمت برای داده های کتاب) کلید و انتخابگر (div.booktitle) برای آنها مقدار باشد. و همچنین شامل اطلاعات منبع مانند نام سایت، آدرسهای اینترنتی که میتوان از آنها برای ایجاد کلاس عنکبوت استفاده کرد.
مسیر مناسبی برای ذخیره عنکبوت ها و مسیر قالب و json بدهید و اسکریپت خود را اجرا کنید، اگر همه چیز خوب باشد، برای همه منابع اضافه شده، عنکبوت خواهید داشت.
1-2 عنکبوت ایجاد شده توسط اسکریپت را با اجرای آن آزمایش کنید و اگر مشکلی وجود داشت، آن را برطرف کنید و اگر از نظر الگو است، همان را به الگو منعکس کنید و می توانید اسکریپت را دوباره اجرا کنید.
شما ایجاد عنکبوت ها را خودکار کردید و می توانید به اضافه کردن عنکبوت ها برای منابع جدید در دسته ها ادامه دهید.
می دانم که برخی از مراحل ممکن است گیج کننده یا ترسناک به نظر برسند، اما نگران نباشید، این یک خلاصه است و اگر می خواهید می توانید مهارت های خود را امتحان کنید. در غیر این صورت، اکنون قصد دارم هر مرحله را با جزئیات توضیح دهم.
بیایید مقاله را در سه بخش اصلی تقسیم کنیم:1) راه اندازی محیط و عنکبوت اساسی2) اجزای اسکراپی را پیش ببرید3) اتوماسیون عنکبوت
اگر از دو قسمت اول آگاه هستید، می توانید مستقیماً به قسمت سوم بروید اتوماسیون عنکبوت (شما می توانید کد دو مرحله اول را از مخزن Github دریافت کنید)
1) راه اندازی محیط و عنکبوت اساسی
*1. ایجاد یک محیط مجازی *
Python Eco-system گزینه های زیادی برای ایجاد محیط مجازی دارد، با این حال، کاندا و venv دو رویکرد محبوب است.
با استفاده از هر یک می توانید یک محیط مجازی ایجاد کنید کاندا یا venv با پایتون 3.10 یا بالاتر:
به عنوان مثال نام env من scrapy-demo است
با استفاده از venv:
$python -m venv myenv
$python -m venu scrapy-demo
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
استفاده از conda:
$conda create –name myenv python=3.10
$ conda create –name scrapy-demo python=3.10
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
هنگامی که محیط را ایجاد کردید، می توانید آنها را بر این اساس فعال کنید:
#if you are using conda
$conda activate scrapy-demo
#if you are using venv
$source scrapy-demo/bin/activate
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
*2. Scrapy را نصب کنید *پس از اینکه محیط مجازی را کرید و فعال کردید، اکنون نوبت به نصب scrapy و شروع پروژه رسیده است. قبل از آن اجازه دهید یک پوشه برای پروژه scrapy جدید خود ایجاد کنیم و برای تمام عملیات های آینده داخل آن حرکت کنیم.
$mkdir scrapy-spiders-automation-demo
$cd scrapy-spiders-automation-demo
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
Scrapy (وب سایت رسمی) را با استفاده از pip یا conda نصب کنید (برای دستورالعمل های دقیق دنبال کنید):
#pip
(scrapy-demo)~/projects/scrapy-spiders-automation-demo$pip install scrapy
#conda
(scrapy-demo)~/projects/scrapy-spiders-automation-demo$conda install conda-forge::scrapy
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
3. یک پروژه خراب ایجاد کنید
ایجاد یک پروژه اسکرپی برای ایجاد و اجرای یک عنکبوت اجباری نیست، با این حال، بهتر است یک پروژه برای پروژه بزرگتر داشته باشید. بنابراین، بیایید یک پروژه با استفاده از scrapy startproject ایجاد کنیم: (از داخل در پوشه پروژه** scrapy-spiders-automation-demo**)
(scrapy-demo)$scrapy startproject spiders_automation_demo
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
این یک پروژه ایجاد می کند
پروژه جدید Scrapy 'spiders_automation_demo'،
با استفاده از دایرکتوری قالب '…/anaconda3/envs/scrapy-demo/lib/python3.10/site-packages/scrapy/templates/project'،
ایجاد شده در:…./دموی-اتوماسیون-عنکبوت-اسکراپی/دمو_عنکبوت_اتوماسیون
می توانید اولین عنکبوت خود را با موارد زیر شروع کنید:
$cd spiders_automation_demo
$scrapy genspider example example.com
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
در اینجا، پیام خودکار در مورد دایرکتوری الگو بسیار مهم است، به عنوان مثال، scrapy از یک الگو برای ایجاد فایل های کد boilerplate برای پروژه ها استفاده می کند. همین امر برای ایجاد عنکبوت با دستوراتی مانند استفاده می شود scrapy genspider example example.com. در قسمت 3، ما قصد داریم از مفاهیم مشابه برای ایجاد خودکار عنکبوت ها با مقادیر و کد خود استفاده کنیم.
spiders_automation_demo/
├── scrapy.cfg
└── spiders_automation_demo
├── __init__.py
├── items.py
├── middlewares.py
├── pipelines.py
├── settings.py
└── spiders
└── __init__.py
3 directories, 7 files
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
4. یک عنکبوت ایجاد کنید
اکنون زمان ایجاد اولین عنکبوت است. قبل از آن اجازه دهید دوباره کار خراش دادن را بیان کنیم. ما میخواهیم دادههای مربوط به نقلقولها را از وبسایت خراش دهیم. برای این دمو، ما از منبع محبوب https://quotes.toscrape.com/ استفاده می کنیم و برای نشان دادن استفاده از قالب و اتوماسیون عنکبوت، یک وب سایت ساده شبیه به نقل قول ایجاد کرده ام. بنابراین، می توانیم از لینک زیر برای منبع دیگر استفاده کنیم، یعنی https://quotes-scrape.netlify.app/
قرار است استفاده کنیم عنکبوت جنسی از دستور scrapy tool برای ایجاد اولین عنکبوت.
(scrapy-demo)$scrapy genspider Quotes https://quotes.toscrape.com/
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
دستور بالا وقتی در پوشه پروژه و محیط اجرا می شود، یک عنکبوت با نام داده شده (به نقل از Quotes) ایجاد می کند و مقداردهی اولیه می کند. دامنه ها و استارتارها متغیر درون عنکبوت ها بنابراین، پس از اجرای دستور، اطلاعات زیر را مشاهده خواهید کرد.
عنکبوت “نقل قول” را با استفاده از الگوی “basic” در ماژول ایجاد کرد:spiders_automation_demo.spiders.quotes
و یک نام فایل Quotes.py زیر پوشه spiders/ ایجاد می شود که دارای کد دیگ بخار زیر است:
import scrapy
class QuotesSpider(scrapy.Spider):
name = “Quotes”
allowed_domains = [“quotes.toscrape.com”]
start_urls = [“https://quotes.toscrape.com/”]
def parse(self, response):
pass
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
می توانید مشاهده کنید که کد بسیار محدودی دارد و چیزهای زیادی برای نوشتن توسط توسعه دهنده باقی مانده است. و حتما ملاحظه کرده اید که این کد با استفاده از آن ایجاد شده است پایه ای الگوی خراشیده “عنکبوت “نقل قول” را با استفاده از الگوی “basic” در ماژول ایجاد کرد:”. بنابراین، بعداً ما از همان رویکرد استفاده خواهیم کرد، اما از الگوی خودمان پر شده با کدهای بیشتر مخصوص کار خراش دادن خود استفاده خواهیم کرد، بنابراین به حداقل تغییرات نیاز خواهیم داشت تا عنکبوت برای منبع خاصی کار کند.
حالا، بیایید جلو برویم و اولین عنکبوت را برای خراش دادن نقل قول ها تکمیل کنیم. ما برای هر نقل قول تنها دو مقدار دریافت می کنیم: عنوان و نویسنده. بنابراین، پس از افزودن کد مورد نیاز، کد عنکبوتی مانند زیر به نظر می رسد.
import scrapy
class QuotesSpider(scrapy.Spider):
name = “Quotes”
allowed_domains = [“quotes.toscrape.com”]
start_urls = [“https://quotes.toscrape.com/”]
def parse(self, response):
#each quote is within
quotes = response.css(“div.quote”)
for quote in quotes:
#each quote text is within
title=quote.css(“span.text::text”).get()
#each author info is within
author =quote.css(“small.author::text”).get()
yield{
‘title’:title,
‘author’:author
}
Enter fullscreen mode
Exit fullscreen mode
You can download the code from the repo Link or copy from gist Link.
The above code is based on the understanding of html that is outcome of ‘inspect’ option in chrome. You can see the source of page in the below screenshot:
You can observe that each quote is under a (blue rectangle) so we can get the html of all quotes by using “div.quote” selector and so the line quotes = response.css(“div.quote”) will تمام نقل قول ها را ارائه می دهد و سپس در حلقه، می توانیم متن و نویسنده را برای هر نقل قول با استفاده از آن استخراج کنیم “span.text::text” و “small.author::text” انتخابگر به ترتیب. حتما متوجه شده اید “::متن” با عنوان و نویسنده در حالی که در نقل قول نیست، به این دلیل است که، ما فقط می خواهیم متن یعنی مقدار درون هر تگ.
هنگامی که عنکبوت شما آماده شد، می توانید عنکبوت خود را برای خراش دادن داده ها با استفاده از دستور scrapy crawl و فقط با ارسال نام عنکبوت به عنوان آرگومان یعنی نقل قول در مثال زیر اجرا کنید: (شما باید در پوشه پروژه scrapy باشید تا scrapy مسیر عنکبوت ها را بشناسد)
(scrapy-demo)$scrapy crawl Quotes
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
اگر خروجی زیر را در ترمینال خود مشاهده کردید:
2024-07-27 18:56:37 [scrapy.core.scraper] DEBUG: Scraped from
{‘title’: ‘“The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”’, ‘author’: ‘Albert Einstein’}
2024-07-27 18:56:37 [scrapy.core.scraper] DEBUG: Scraped from
{‘title’: ‘“It is our choices, Harry, that show what we truly are, far more than our abilities.”’, ‘author’: ‘J.K. Rowling’}
2024-07-27 18:56:37 [scrapy.core.scraper] DEBUG: Scraped from
{‘title’: ‘“There are only two ways to live your life. One is as though nothing is a miracle. The other is as though everything is a miracle.”’, ‘author’: ‘Albert Einstein’}
2024-07-27 18:56:37 [scrapy.core.scraper] DEBUG: Scraped from
{‘title’: ‘“The person, be it gentleman or lady, who has not pleasure in a good novel, must be intolerably
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
تبریک می گویم ! اولین عنکبوت شما آماده است و داده ها را خراش می دهد.
2) اجزای اسکراپی را پیش ببرید
*5. تست و ایجاد اجزای دیگر *اکنون، ما یک عنکبوت اولیه برای خراش دادن نقل قول از منبع وب داده شده داریم. بیایید سیستم خراش دادن را با ایجاد سایر اجزای یک اسکراپر مانند اقلام، اقلام، خطوط لوله و غیره قوی تر کنیم.
5.1. موارد، **مورد ** در scrapy نوعی ساختار برای داده هایی است که ما در حال خزیدن هستیم. اجرای موارد مختلف تمیز کردن و طرحواره در کل فرآیند خراش دادن و کمک به کاهش خطاها در خراش دادن داده ها بسیار مفید است.
فرآیند ایجاد آیتم بسیار آسان است. پوشه پروژه شما از قبل دارای یک است items.py فایل (spiders_automation_demo/items.py)، بنابراین شما فقط باید یک کلاس (QuoteItem()) برای مورد خود اضافه کنید و می توانید با ارث بردن این کار را انجام دهید. scrapy.Item کلاس این items.py فایل برای Quotes.pyعنکبوت به شکل زیر خواهد بود: (# برای جزئیات بیشتر در مورد مورد، به مستندات مراجعه کنید)
#spiders_automation_demo/items.py
import scrapy
class QuoteItem(scrapy.Item):
title = scrapy.Field()
author = scrapy.Field()
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
شما می توانید نام کلاس مورد خود را هر چیزی، در مثالی که ما استفاده کرده ایم، بگذارید QuoteItem().
اکنون آیتم شما آماده است و برای استفاده از این آیتم در spider خود (Quotes.py)، باید تغییرات کمی در کد قبلی به شرح زیر انجام دهید:
import scrapy
from spiders_automation_demo.items import QuoteItem
class QuotesSpider(scrapy.Spider):
name = “Quotes”
allowed_domains = [“quotes.toscrape.com”]
start_urls = [“https://quotes.toscrape.com/”]
def parse(self, response):
#each quote is within
quotes = response.css(“div.quote”)
for quote in quotes:
#create your item object
quote_item = QuoteItem()
#each quote text is within
title=quote.css(“span.text::text”).get()
#each author info is within
author =quote.css(“small.author::text”).get()
#add your selector to your item
quote_item[‘title’]=title
quote_item[‘author’]= author
#yield your item
yield quote_item
Enter fullscreen mode
Exit fullscreen mode
You can observe that we have made following changes to previous spdier code:
import your item to the spider (note: the import path may change as per your project name)from spiders_automation_demo.items import QuoteItem
Create an object of for your itemquote_item = QuoteItem()
Add your selector to the item (you can do it directly instead of using title and author variable like:
title=quote.css(“span.text::text”).get()
quote_item[‘title’]=title
#the above two lines can be replaced by a single line
quote_item[‘title’]=quote.css(“span.text::text”).get()
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
آخرین تغییر، بهجای ویژگیهای فردی، شیء مورد را ارائه میکند.
yield quote_item
همین است. عنکبوت شما در حال حاضر از آیتم استفاده می کند و در مورد خراش دادن و نامگذاری داده ها در این فرآیند سختگیرانه تر است. برای آزمایش این، میتوانید «عنوان» را به «متن» در items.py تغییر دهید و spider را اجرا کنید. خطای زیر را خواهید دید:
KeyError: ‘QuoteItem does not support field: title’
این خطا به خودی خود توضیح داده شده است، که در عنکبوت ما سعی می کنیم ارزش عنوان را بدست آوریم اما عنوانی در QuoteItem ما وجود ندارد. چنین بررسی هایی به کاهش خطا در پروژه خراش داده های بزرگ کمک می کند. بعداً همان آیتم def را خواهید دید. می تواند برای تمیز کردن داده ها یا اجرای طرحواره داده یا نظارت و غیره استفاده شود.
با استفاده از gist items.py و spider می توانید کدهای items.py و spider اصلاح شده را کپی کنید
*5.2. بارگذار آیتم *
لودر آیتم نوعی پردازش داده های خراشیده شده قبل از ذخیره آن است. به عنوان مثال، فرض کنید می خواهید همه نقل قول ها را با حروف عنوان یا بزرگ بخواهید یا هر کاراکتر خاصی را حذف کنید. می توانید این کار را پس از خراش دادن و ذخیره داده ها انجام دهید، با این حال، چنین پردازشی قبل از ذخیره سازی آسان تر است و itemLoader راه های کارآمد برای انجام آن را به طور منظم ارائه کنید.
حال سوال این است که چگونه استفاده کنیم itemLoader? سه مکان / ترتیب برای استفاده از آن وجود دارد:
همراه با کد مورد (شما حتی می توانید منطق itemLoader و آیتم را با هم ادغام کنید) در فایل items.py.
همراه با کد عنکبوتی در Quotes.py
فایل خارجی در پروژه شما یعنی itemsloaders.py
برای پروژه کوچکتر گزینه اول یا دوم مشکلی ندارد اما برای پروژه بزرگتر بهتر است یک فایل خارجی برای itemLoader داشته باشید و از این روش استفاده می کنم.
بنابراین، فقط یک فایل پایتون در پروژه خود به همان سطح فایل items.py ایجاد کنید spiders_automation_demo/itemsloader.py و کد زیر را اضافه کنید:
#spiders_automation_demo/itemsloader.py
#required imports
from scrapy.loader import ItemLoader
from scrapy.loader.processors import TakeFirst
#define your methods to apply on item value
def to_title_case(title):
return title.title()
#define your loader class
class QuoteLoader(ItemLoader):
default_output_processor = TakeFirst()
title_in = MapCompose(str.strip, to_title_case)
author_in = MapCompose(str.strip, to_title_case)
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
بنابراین، itemLoader شما آماده است و اکنون باید spider Quote.py خود را برای استفاده از itemloader تغییر دهید.
import scrapy
from spiders_automation_demo.items import QuoteItem
from spiders_automation_demo.itemsloader import QuoteLoader
class QuotesSpider(scrapy.Spider):
name = “Quotes”
allowed_domains = [“quotes.toscrape.com”]
start_urls = [“https://quotes.toscrape.com/”]
def parse(self, response):
#each quote is within
quotes = response.css(“div.quote”)
for quote in quotes:
#create your item object
#quote_item = QuoteItem()
#create your loader
loader = QuoteLoader(item=QuoteItem(), selector=quote)
#add your selector to your item
#each quote text is within
loader.add_css(‘title’,”span.text::text”)
#each author info is within
loader.add_css(‘author’,”small.author::text”)
#yield your item via the loader using .load_item()
yield loader.load_item()
Enter fullscreen mode
Exit fullscreen mode
import your itemloader to your spiderfrom scrapy.loader.processors import TakeFirst,MapCompose
create the loader object using your itemloaderloader = QuoteLoader(item=QuoteItem(), selector=quote)
Make changes with selector to use loader
loader.add_css(‘title’,”span.text::text”)
loader.add_css(‘author’,”small.author::text”)
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
بازده خود را برای استفاده از لودر تغییر دهید
loader.load_item()
اکنون، عنکبوت به روز شده خود را اجرا و آزمایش کنید و مشاهده خواهید کرد که تمام متن های نقل قول در حروف عنوان هستند، به عنوان مثال: متن اصلی نقل قول
«سعی کنید مرد موفقی نشوید. بلکه تبدیل به یک مرد با ارزش شوید.»
به عنوان TitleCase تبدیل می شود
«سعی نکنید مرد موفقی شوید. در عوض مردی با ارزش شوید.»
5.3. خطوط لوله
ما در کار جمع آوری داده ها با عنکبوت ها پیشرفت کافی داشته ایم. حالا بیایید عنکبوت ها را برای فعال کردن به روز کنیم خطوط لوله در پروژه ما
گزینه Pipelines در Scrapy مکانی عالی برای انجام عملیات های مختلف پس از خراشیدن و بارگیری یک آیتم توسط آیتم لودر است. خطوط لوله می توانند سطح پیشرفته تری از تمیز کردن و پردازش داده ها را در طول فرآیند خراش دادن داده ها داشته باشند. به عنوان مثال، حذف یک مورد بر اساس هر شرایطی، مانند موارد تکراری (همان عنوان برای نقل قول) یا مقدار از دست رفته (بدون ارزش برای نویسنده). چنین الزاماتی را می توان از طریق خط لوله پیکربندی کرد. می توانید اطلاعات بیشتری در مورد خط لوله از سند اسکرپی در لینک بخوانید
برای مثال، میخواهم خط لولهای ایجاد کنم که فقط آن نقل قولهایی را که «عشق» یا «زندگی» در عنوان دارند، حفظ کنم، بنابراین اگر یکی از این دو کلمه در دسترس نباشد، آن نقل قول ذخیره یا پردازش نخواهد شد.
هر خط لوله ای را می توان در فایل pipelines.py در پروژه ایجاد کرد که به عنوان کد boilerplate پس از ایجاد پروژه ایجاد شد، یعنی (spiders_automation_demo/pipelines.py)
from scrapy.exceptions import DropItem
class FilterQuotesPipelineLoveOrLife:
def process_item(self, item, spider):
# Check if ‘love’ or ‘life’ is in the text
if ‘love’ in item[‘title’].lower() or ‘life’ in item[‘title’].lower():
return item
else:
raise DropItem(f”Quote without ‘love’ or ‘life’ in title text: {item[‘title’]}”)
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
کد خط لوله ساده است، شما باید یک کلاس برای یک خط لوله جداگانه ایجاد کنید FilterQuotesPipelineLoveOrLife
و منطق را در متد کلاس process_item() اضافه کنید.
خط لوله را فعال کنید: برخلاف آیتم یا بارگذار آیتم، خط لوله با وارد کردن آن به عنکبوت کار نمی کند. اما، شما باید خط لوله خود را در settings.py فعال کنید (دوباره، این فایل از قبل در پوشه پروژه شما وجود دارد و در طول فرآیند اولیه سازی پروژه ایجاد شده است). شما می توانید خط لوله جدید ایجاد شده خود را به صورت زیر اضافه کنید (بخش نظر داده شده را در settings.py بیابید و بر اساس آن اصلاح کنید:
# Enable the custom pipeline
ITEM_PIPELINES = {
‘spiders_automation_demo.pipelines.FilterQuotesPipelineLoveOrLife’: 300,
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
این همه است، خط لوله شما برای فیلتر کردن متن نقل قول با «عشق» یا «زندگی» آماده است و نیازی به تغییر عنکبوت قبلی خود ندارید. می توانید عنکبوت را اجرا کنید و خط لوله خود را آزمایش کنید. در Scrapy log زیر را مشاهده خواهید کرد “هشدار” پیام (و اگر داده های خود را ذخیره کنید، می بینید که فقط دو نقل قول ذخیره شده است.):
هشدار: حذف شد: نقل قول بدون «عشق» یا «زندگی» در متن عنوان: «این انتخابهای ما هستند، هری، آنچه را که واقعاً هستیم، بسیار بیشتر از تواناییهایمان نشان میدهند».{'نویسنده': 'جی کی رولینگ'،'title': '”این انتخاب های ما هستند، هری، که نشان می دهد ما واقعا چه هستیم، خیلی بیشتر””از توانایی های ما.”}
5.4. تغذیه می کند
تا به حال، ما شاهد اجرای خروجی عنکبوت خود در ترمینال بودهایم و این فقط در هنگام آزمایش خوب است، اما در یک پروژه واقعی باید دادههای خزیده شده/خراششده را ذخیره کنید.
ابزار Scrapy به پارامتر / آرگومان (-o یا -O) اجازه می دهد تا نام فایل را برای ذخیره خروجی به فایل مشخص شده از طریق خط فرمان، مانند:
$scrapy crawl quotes -o quotes.json
$scrapy crawl quotes -O quotes.json
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
با -o و -O تفاوت وجود دارد (یعنی حروف کوچک و بزرگ)
'-o': داده ها را در صورت وجود به فایل اضافه می کند
'-O': فایل را در صورت وجود بازنویسی می کند.
با این حال، در پروژههای واقعی، ما میخواهیم نام فایل، مسیر و نوع فایل را به روشهای بهتری مشخص کنیم تا نظارت و نگهداری آن آسان باشد. Scrapy راه آسانی را برای دستیابی به آن با پیکربندی فراهم می کند تغذیه در settings.py (شبیه به پیکربندی خط لوله). باید فرهنگ لغت پایتون زیر را به settings.py اضافه کنید و با ذخیره کردن آن به صورت مشخص شده، داده های خراشیده شده را پایدار می کند.
ما از نام عنکبوت برای ذخیره داده های خراشیده شده استفاده می کنیم (به فکر ردیابی داده ها توسط عنکبوت ها) و امکان بازنویسی اگر نام فایل از قبل وجود داشته باشد (مشابه آرگومان -O از طریق خط فرمان).
FEEDS = {
‘%(name)s_quotes.json’: {
‘format’: ‘json’,
‘overwrite’: True,
},
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
توضیح
%(name)s_quotes.json: از نام عنکبوت به عنوان پیشوند فایل خروجی استفاده می کند.
format: 'json': مشخص می کند که فرمت خروجی JSON باشد.
overwrite: True: اطمینان حاصل می کند که اگر فایل از قبل وجود داشته باشد، رونویسی شده است.
حال، اگر عنکبوت خود را در انتها اجرا کنید، یک فایل json ایجاد میشود (Quotes_quotes.json) و تمام نقل قولهای خراشیده و فیلتر شده خواهد بود. مانند:
[{
“title”: ““There Are Only Two Ways To Live Your Life. One Is As Though Nothing Is A Miracle. The Other Is As Though Everything Is A Miracle.””,
“author”: “Albert Einstein”
},
{
“title”: ““It Is Better To Be Hated For What You Are Than To Be Loved For What You Are Not.””,
“author”: “André Gide”
}
]
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
5.5. تنظیمات
در حال حاضر، شما قبلاً از settings.py برای خط لوله و فیدها استفاده کردهاید، با این حال پیکربندیهای بیشتری وجود دارد که میتوان آنها را از طریق settings.py تنظیم یا لغو تنظیم کرد و بر اساس پروژه اعمال میشود. بنابراین، شما همچنین می توانید با استفاده از گزینه custom_settings، تنظیماتی را برای عنکبوت در کد عنکبوتی ایجاد کنید. با این حال، ما قرار نیست از این برای این نسخه ی نمایشی استفاده کنیم. شما می توانید خودتان را کشف کنید.
اگر settings.py را باز کرده باشید، به طور پیشفرض گزینههای فعالسازی زیادی را میبینید. مانند:
BOT_NAME = “spiders_automation_demo”
SPIDER_MODULES = [“spiders_automation_demo.spiders”] NEWSPIDER_MODULE = “spiders_automation_demo.spiders”
# Obey robots.txt rules
ROBOTSTXT_OBEY = True
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
ما با sandbox یا وب سایت منبع ساختگی کار می کنیم، بنابراین نیازی به انجام تنظیمات زیادی از جمله ROBOTSTXT_OBEY نداریم، بسیاری از سایت ها اجازه خزیدن را نمی دهند و با استفاده از فایل robot.txt اطلاع رسانی می شود، بنابراین اگر ROBOTSTXT_OBEY=True باشد، scrapy آن را پاک نمی کند. اگر میخواهید خزیدن را اعمال کنید، میتوانید آن را نادرست تنظیم کنید (ROBOTSTXT_OBEY=True).
robots.txt یک کنوانسیون است، بنابراین به خودی خود دست از خراش نمی کشد، بلکه فقط یک رویکرد اخلاقی برای احترام به robots.txt است.
3) اتوماسیون عنکبوت
اکنون پروژه خراش دادن شما با 1 عنکبوت با سایر اجزای مورد نیاز آماده است. بنابراین، اکنون بیایید به درک فرآیند اتوماسیون و نحوه ایجاد عنکبوت ها برای خراش دادن نقل قول از منابع دیگر مانند سایر سایت های ساختگی حرکت کنیم:
فرآیند دستی:
اجازه دهید ابتدا روند دستی را طی کنیم. شما دو گزینه دارید:
با استفاده از scrapy genspider یک عنکبوت جدید ایجاد کنید و روش تجزیه را کپی کنید
$scrapy genspider QuotesAjitSource https://quotes-scrape.netlify.app/
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
import scrapy
class QuoteajitsourceSpider(scrapy.Spider):
name = “QuotesAjitSource”
allowed_domains = [“quotes-scrape.netlify.app”]
start_urls = [“https://quotes-scrape.netlify.app/”]
def parse(self, response):
pass
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
یک فایل پایتون ایجاد کنید و کد پیست را از عنکبوت قبلی کپی کنید
در هر دو روش، شما کد را برای عنکبوت جدید یعنی برای هر منبع جدید کپی، پیست و اصلاح می کنید. و اگر به خاطر داشته باشید، ما با مشکل یک پروژه خراش دادن با بیش از 1000 منبع شروع کردیم.
بیایید روند دستی را مانند منبع قبلی دنبال کنیم. استفاده کنید بازرسی گزینه ها در کروم
##spiders_automation_demo/spiders/QuotesAjitSource.py
import scrapy
from spiders_automation_demo.items import QuoteItem
from spiders_automation_demo.itemsloader import QuoteLoader
class QuoteajitsourceSpider(scrapy.Spider):
name = “QuotesAjitSource”
allowed_domains = [“quotes-scrape.netlify.app”]
start_urls = [“https://quotes-scrape.netlify.app/”]
def parse(self, response):
#each quote is within
quotes = response.css(“div.quote-container”)
for quote in quotes:
#create your item object
#quote_item = QuoteItem()
#create your loader
loader = QuoteLoader(item=QuoteItem(), selector=quote)
#add your selector to your item
#each quote text is within
loader.add_css(‘title’,”h2.title::text”)
#each author info is within
loader.add_css(‘author’,”p.author::text”)
#yield your item via the loader using .load_item()
yield loader.load_item()
Enter fullscreen mode
Exit fullscreen mode
The output json file will be empty because there are not quotes with ‘love’ or ‘life’ word in it. So, let’s modify our filter pipeline and add ‘work’ to it.
from scrapy.exceptions import DropItem
class FilterQuotesPipelineLoveOrLife:
def process_item(self, item, spider):
# Check if ‘love’ or ‘life’ is in the text
if ‘love’ in item[‘title’].lower() or ‘life’ in item[‘title’].lower() or ‘work’ in item[‘title’].lower():
return item
else:
raise DropItem(f”Quote without ‘love’ or ‘life’ or ‘work’ in title text: {item[‘title’]}”)
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
اکنون فایل json خروجی خود را باز کنید و نقل قول های زیر را خواهید داشت:
[{
“title”: “If I Find 10,000 Ways Something Won’T Work, I Haven’T Failed. I Am Not Discouraged, Because Every Wrong Attempt Discarded Is Another Step Forward.”,
“author”: “— Thomas Edison”
},
{
“title”: “As A Cure For Worrying, Work Is Better Than Whisky.”,
“author”: “— Thomas Edison”
}
]
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
اکنون، شما دو عنکبوت دارید، پس بیایید بررسی کنیم که تفاوت بین این عنکبوت ها چیست. ما از ابزارهای diff برای برجسته کردن تفاوت بین این دو عنکبوت استفاده کرده ایم. از طریق لینک هم میتونید چک کنید
اگر تفاوت کد عنکبوت را مشاهده کنید، موارد زیر را متوجه خواهید شد:
مقادیر / فراداده خاص عنکبوت
نام کلاس عنکبوت
نام عنکبوت
مقدار در مجاز_دامنه ها
مقدار در start_urls
مقادیر خاص منبع، عمدتاً ارزش انتخابگرها
مقدار انتخابگر برای div اصلی که نقل قول فردی را نگه می دارد
مقدار انتخابگر برای عنوان حاوی متن عنوان نقل قول فردی
مقدار انتخابگر برای نویسنده ای که متن نویسنده نقل قول فردی را نگه می دارد
فرآیند خودکار: استفاده از قالب برای spdier و json
1. یک فایل json ایجاد کنید
یک فایل json ایجاد کنید که در آن هر یک از ویژگی های آیتم (به عنوان مثال: عنوان و نویسنده) کلید و انتخابگر (div.title) برای آنها مقدار باشد. و همچنین شامل اطلاعات منبع مانند نام سایت، آدرسهای اینترنتی که میتوان از آنها برای ایجاد کلاس عنکبوت استفاده کرد.
{
“spidername”: “Quotes Ajit Source2”,
“start_urls”: [“https://quotes-scrape.netlify.app/”],
“quote_div_main”: “div.quote-container”,
“title_selector”: “h2.title”,
“author_selector”: “p.author”
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
2. یک فایل قالب ایجاد کنید
ما به الگوی Jinja2 (مستندات) می رویم، بنابراین اجازه دهید با هر کد عنکبوتی شروع کنیم و آن را تغییر دهیم تا قالب Jinja2 را اتخاذ کند.
#spiders_automation_demo/templates/spiders/quotespider_template.jinja2
import scrapy
from spiders_automation_demo.items import QuoteItem
from spiders_automation_demo.itemsloader import QuoteLoader
class {{ spiderclass}}(scrapy.Spider):
name = “{{spidername}}”
allowed_domains = [“{{allowed_domains}}”]
start_urls = {{start_urls}}
def parse(self, response):
#each quote is within
quotes = response.css(“{{quote_div_main}}”)
for quote in quotes:
#create your item object
#quote_item = QuoteItem()
#create your loader
loader = QuoteLoader(item=QuoteItem(), selector=quote)
#add your selector to your item
#each quote text is within
loader.add_css(‘title’,”{{title_selector}}::text”)
#each author info is within
loader.add_css(‘author’,”{{author_selector}}::text”)
#yield your item via the loader using .load_item()
yield loader.load_item()
Enter fullscreen mode
Exit fullscreen mode
3. Create python script to generate spider( using template and json file created in previous stop)
#bluk_gen_spiders.py
import json
from jinja2 import Environment, FileSystemLoader
from urllib.parse import urlparse
import os
# Load JSON configuration
with open(‘sources.json’) as f:
sources = json.load(f)
# Set up Jinja2 environment
env = Environment(loader=FileSystemLoader(‘spiders_automation_demo/templates/spiders/’))
template = env.get_template(‘quotespider_template.jinja2’)
# Folder where you want to save the spider file
folder_name = ‘spiders_automation_demo/spiders’
for config in sources:
# Extract values and manipulate strings
spidername = config[‘spidername’].title().replace(” “, “”)
spiderclass = spidername.capitalize()+’Spider’
start_urls = config[‘start_urls’]
parsed_url = urlparse(start_urls[0])
allowed_domains = parsed_url.netloc
# Render the template with values
output = template.render(
spiderclass=spiderclass,
spidername=spidername,
allowed_domains=allowed_domains,
start_urls=start_urls,
quote_div_main=config[‘quote_div_main’],
title_selector=config[‘title_selector’],
author_selector=config[‘author_selector’]
)
# Ensure the folder exists
os.makedirs(folder_name, exist_ok=True)
# Save the rendered template to a new Python file in the specified folder
file_path = os.path.join(folder_name, f'{spiderclass}.py’)
with open(file_path, ‘w’) as f:
f.write(output)
print(f”Spider generated: {file_path}”)
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
تعیین مسیر مناسب برای نگهداری عنکبوت ها (folder_name=”spiders_automation_demo/spiders”) و مسیر قالب (env = Environment(loader=FileSystemLoader(‘spiders_automation_demo/templates/spiders/’))) و json و اسکریپت خود را اجرا کنید. مثلا:
(scrapy-demo)$python bluk_gen_spiders.py
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
اگر همه چیز خوب باشد، برای همه منابع اضافه شده در زیر پوشه spiders پروژه، عنکبوت خواهید داشت. (در مکان اسکریپت دقت کنید)
اکنون، می توانید 1-2 عنکبوت ایجاد شده توسط اسکریپت نسل را اجرا و آزمایش کنید و در صورت مشکل، آن را برطرف کنید (چه در اسکریپت نسل یا در فایل قالب) و می توانید اسکریپت را دوباره اجرا کنید.
اکنون، از روی کنجکاوی، فقط به کد spider Manual در مقابل ایجاد شده توسط اسکریپت با استفاده از الگو و json نگاهی بیندازید. پیوند تفاوت می توانید متوجه شوید که هیچ تفاوتی در کد وجود ندارد (نقل قول های تکی و دوگانه در starts_url نیز قابل رفع هستند :))
تبریک می گویم !! شما ایجاد عنکبوتها را خودکار کردهاید و میتوانید فقط با اضافه کردن پنج مقدار در دستهها، عنکبوتها را برای منابع جدید اضافه کنید. sources.json.
به عنوان مثال، اگر دو منبع دیگر برای نقل قول ها پیدا کردید و می خواهید برای هر کدام عنکبوت اضافه کنید:1) آدرس اینترنتی نقل قول مغزی
2) نقل قول های AZ [URL]
سپس، شما فقط باید صفحات وب مربوطه را بررسی کنید و فایل sources.json را به صورت زیر تغییر دهید:
[{
“spidername”: “Quote Ajit Source”,
“start_urls”: [“https://quotes-scrape.netlify.app/”],
“quote_div_main”: “div.quote-container”,
“title_selector”: “h2.title”,
“author_selector”: “p.author”
},
{
“spidername”: “Brainy Quote”,
“start_urls”: [“https://www.brainyquote.com/topics/life-quotes”],
“quote_div_main”: “div.grid-item.qb.clearfix.bqQt”,
“title_selector”: “div”,
“author_selector”: “a.bq-aut.qa_109542.oncl_a”
},
{
“spidername”: “AZ Quotes”,
“start_urls”: [“https://www.azquotes.com/quotes/topics/life.html”],
“quote_div_main”: “div.wrap-block”,
“title_selector”: “p a.title”,
“author_selector”: “div.author a”
}
]
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
اکنون، اسکریپت تولید عنکبوت خود را مجدداً به صورت زیر اجرا کنید و اکنون سه عنکبوت جدید ایجاد خواهید کرد (شما می توانید کدی را اضافه کنید تا عنکبوت ایجاد نشود اگر نام قبلاً وجود دارد).
(scrapy-demo)$python bluk_gen_spiders.py
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
توجه: با این حال، عنکبوت جدید ایجاد شده برای Brainy Quote یک خطای 403 (محدودیت خزیدن) می دهد، بنابراین داده ها نمی توانند با تنظیمات فعلی خراشیده شوند و دور زدن محدودیت موضوع دیگری برای چند روز دیگر است.
شما spider را برای نقل قول های AZ اجرا می کنید و داده های زیر را در فایل json دریافت خواهید کرد (AzQuotes_quotes.json):
(scrapy-demo)$scrapy crawl AzQuotes
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
[{
“title”: “The Happiness Of Your Life Depends Upon The Quality Of Your Thoughts.”,
“author”: “Marcus Aurelius”
},
{
“title”: “Without Forgiveness Life Is Governed By… An Endless Cycle Of Resentment And Retaliation.”,
“author”: “Roberto Assagioli”
},
{
“title”: “The Tragedy Of Life Is What Dies Inside A Man While He Lives.”,
“author”: “Albert Schweitzer”
},
……truncated
]
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
توجه: مقاله در وضعیت بازبینی قرار دارد بنابراین ممکن است اشتباهات تایپی، گرامری و خطاهای فنی وجود داشته باشد. بنابراین، در صورت مشاهده هرگونه خطای فنی، از طریق نظر به من اطلاع دهید، بنابراین در نسخه اصلاح شده آن را برطرف خواهم کرد.
در ادامه بخوانید
پایتون بهتر از جاوا اسکریپت است!
مایا رامکیشون – 3 جولای
پایتون: از مبتدی تا حرفه ای در 30 دقیقه (قسمت 1)
اسکافیلد آیدهن – 16 جولای
خراش دادن نظرات توییتر با سلنیوم (پایتون): راهنمای گام به گام
دیوید هرناندز تورس – 3 جولای
کار با پایگاه داده در جنگو با استفاده از PostgreSQL
شیطون – 2 جولای
امروز، من قصد دارم در مورد اتوماسیون حذف وب خود که اخیراً در حال کار هستم و قصد دارم تاریخ را از هزاران وب سایت حذف کنم، به اشتراک بگذارم. بله، کار بر روی یک پروژه خراش دادن در مقیاس بزرگ.
مسئله :
شما یک پروژه خراش داده جدید دریافت کردید که شامل خراش دادن داده ها از بسیاری از وب سایت های مشابه است. به عنوان مثال، دادههای مربوط به کتابها از وبسایتهای مرتبط با کتابهای مختلف. یا اطلاعات شکلاتی از منابع بسیاری.
ممکن است فکر کنید، مشکل اینجا چیست، می توان با استفاده از آن انجام داد خراشیده یا هر ابزار یا فریمورک مشابه دیگری!
این مانند هر پروژه معمولی خراش دادن داده است اما صبر کنید! اگر منابع از 100 یا 1000 باشد چه!
آیا هنوز هم استفاده می کنید “scrapy genspider 1000 بار و سپس به ویرایش و تغییر هر عنکبوت یکی پس از دیگری؟
راه حل :
پروژه اسکرپی خط پایه خود را ایجاد کنید که دارای 1-2 عنکبوت با تمام اجزای دیگر مانند آیتم ها، آیتم لودر، خط لوله، میان افزارها و تنظیمات مناسب باشد و سپس یک اسکریپت اتوماسیون ایجاد عنکبوت بنویسید که دارای یک فایل قالب (بر اساس 1-2 عنکبوت شما) خواهد بود. یک فایل json دارای جزئیات منبع و انتخابگر برای هر آیتم (در هر منبع). هنگامی که اسکریپت را اجرا می کنید، عنکبوت برای همه منابع موجود ایجاد می شود.
مراحل:
مراحل بسیار ساده خواهند بود، همانطور که به طور انتزاعی در بخش حل ذکر شد. بیایید یک لیست کوتاه در اینجا (از جمله ایجاد محیط مجازی) داشته باشیم:
- ایجاد یک محیط مجازی برای پایتون (Conda یا venv)
- اسکراپی را نصب کنید
- یک پروژه خراب ایجاد کنید
- اولین عنکبوت ساده را برای یک منبع ایجاد کنید
- اجزای دیگر مانند آیتم ها، آیتم لودر، خطوط لوله و غیره را تست و ایجاد کنید.
هنگامی که پروژه خراش دادن شما با 1-2 عنکبوت و سایر اجزا آماده شد. اکنون به سمت اتوماسیون ایجاد عنکبوت بروید (نه فرآیند خراش دادن)
- یک فایل json ایجاد کنید که در آن هر یک از ویژگی های مورد (به عنوان مثال: عنوان، نویسنده، قیمت برای داده های کتاب) کلید و انتخابگر (div.booktitle) برای آنها مقدار باشد. و همچنین شامل اطلاعات منبع مانند نام سایت، آدرسهای اینترنتی که میتوان از آنها برای ایجاد کلاس عنکبوت استفاده کرد.
- مسیر مناسبی برای ذخیره عنکبوت ها و مسیر قالب و json بدهید و اسکریپت خود را اجرا کنید، اگر همه چیز خوب باشد، برای همه منابع اضافه شده، عنکبوت خواهید داشت.
- 1-2 عنکبوت ایجاد شده توسط اسکریپت را با اجرای آن آزمایش کنید و اگر مشکلی وجود داشت، آن را برطرف کنید و اگر از نظر الگو است، همان را به الگو منعکس کنید و می توانید اسکریپت را دوباره اجرا کنید.
- شما ایجاد عنکبوت ها را خودکار کردید و می توانید به اضافه کردن عنکبوت ها برای منابع جدید در دسته ها ادامه دهید.
می دانم که برخی از مراحل ممکن است گیج کننده یا ترسناک به نظر برسند، اما نگران نباشید، این یک خلاصه است و اگر می خواهید می توانید مهارت های خود را امتحان کنید. در غیر این صورت، اکنون قصد دارم هر مرحله را با جزئیات توضیح دهم.
بیایید مقاله را در سه بخش اصلی تقسیم کنیم:
1) راه اندازی محیط و عنکبوت اساسی
2) اجزای اسکراپی را پیش ببرید
3) اتوماسیون عنکبوت
اگر از دو قسمت اول آگاه هستید، می توانید مستقیماً به قسمت سوم بروید اتوماسیون عنکبوت (شما می توانید کد دو مرحله اول را از مخزن Github دریافت کنید)
1) راه اندازی محیط و عنکبوت اساسی
*1. ایجاد یک محیط مجازی *
Python Eco-system گزینه های زیادی برای ایجاد محیط مجازی دارد، با این حال، کاندا و venv دو رویکرد محبوب است.
با استفاده از هر یک می توانید یک محیط مجازی ایجاد کنید کاندا یا venv با پایتون 3.10 یا بالاتر:
به عنوان مثال نام env من scrapy-demo است
با استفاده از venv:
$python -m venv myenv
$python -m venu scrapy-demo
استفاده از conda:
$conda create --name myenv python=3.10
$ conda create --name scrapy-demo python=3.10
هنگامی که محیط را ایجاد کردید، می توانید آنها را بر این اساس فعال کنید:
#if you are using conda
$conda activate scrapy-demo
#if you are using venv
$source scrapy-demo/bin/activate
*2. Scrapy را نصب کنید *
پس از اینکه محیط مجازی را کرید و فعال کردید، اکنون نوبت به نصب scrapy و شروع پروژه رسیده است. قبل از آن اجازه دهید یک پوشه برای پروژه scrapy جدید خود ایجاد کنیم و برای تمام عملیات های آینده داخل آن حرکت کنیم.
$mkdir scrapy-spiders-automation-demo
$cd scrapy-spiders-automation-demo
Scrapy (وب سایت رسمی) را با استفاده از pip یا conda نصب کنید (برای دستورالعمل های دقیق دنبال کنید):
#pip
(scrapy-demo)~/projects/scrapy-spiders-automation-demo$pip install scrapy
#conda
(scrapy-demo)~/projects/scrapy-spiders-automation-demo$conda install conda-forge::scrapy
3. یک پروژه خراب ایجاد کنید
ایجاد یک پروژه اسکرپی برای ایجاد و اجرای یک عنکبوت اجباری نیست، با این حال، بهتر است یک پروژه برای پروژه بزرگتر داشته باشید. بنابراین، بیایید یک پروژه با استفاده از scrapy startproject ایجاد کنیم: (از داخل در پوشه پروژه** scrapy-spiders-automation-demo**)
(scrapy-demo)$scrapy startproject spiders_automation_demo
این یک پروژه ایجاد می کند
پروژه جدید Scrapy 'spiders_automation_demo'،
با استفاده از دایرکتوری قالب '…/anaconda3/envs/scrapy-demo/lib/python3.10/site-packages/scrapy/templates/project'،
ایجاد شده در:
…./دموی-اتوماسیون-عنکبوت-اسکراپی/دمو_عنکبوت_اتوماسیون
می توانید اولین عنکبوت خود را با موارد زیر شروع کنید:
$cd spiders_automation_demo
$scrapy genspider example example.com
در اینجا، پیام خودکار در مورد دایرکتوری الگو بسیار مهم است، به عنوان مثال، scrapy از یک الگو برای ایجاد فایل های کد boilerplate برای پروژه ها استفاده می کند. همین امر برای ایجاد عنکبوت با دستوراتی مانند استفاده می شود scrapy genspider example example.com
. در قسمت 3، ما قصد داریم از مفاهیم مشابه برای ایجاد خودکار عنکبوت ها با مقادیر و کد خود استفاده کنیم.
spiders_automation_demo/
├── scrapy.cfg
└── spiders_automation_demo
├── __init__.py
├── items.py
├── middlewares.py
├── pipelines.py
├── settings.py
└── spiders
└── __init__.py
3 directories, 7 files
4. یک عنکبوت ایجاد کنید
اکنون زمان ایجاد اولین عنکبوت است. قبل از آن اجازه دهید دوباره کار خراش دادن را بیان کنیم. ما میخواهیم دادههای مربوط به نقلقولها را از وبسایت خراش دهیم. برای این دمو، ما از منبع محبوب https://quotes.toscrape.com/ استفاده می کنیم و برای نشان دادن استفاده از قالب و اتوماسیون عنکبوت، یک وب سایت ساده شبیه به نقل قول ایجاد کرده ام. بنابراین، می توانیم از لینک زیر برای منبع دیگر استفاده کنیم، یعنی https://quotes-scrape.netlify.app/
قرار است استفاده کنیم عنکبوت جنسی از دستور scrapy tool برای ایجاد اولین عنکبوت.
(scrapy-demo)$scrapy genspider Quotes https://quotes.toscrape.com/
دستور بالا وقتی در پوشه پروژه و محیط اجرا می شود، یک عنکبوت با نام داده شده (به نقل از Quotes) ایجاد می کند و مقداردهی اولیه می کند. دامنه ها و استارتارها متغیر درون عنکبوت ها بنابراین، پس از اجرای دستور، اطلاعات زیر را مشاهده خواهید کرد.
عنکبوت “نقل قول” را با استفاده از الگوی “basic” در ماژول ایجاد کرد:
spiders_automation_demo.spiders.quotes
و یک نام فایل Quotes.py زیر پوشه spiders/ ایجاد می شود که دارای کد دیگ بخار زیر است:
import scrapy
class QuotesSpider(scrapy.Spider):
name = "Quotes"
allowed_domains = ["quotes.toscrape.com"]
start_urls = ["https://quotes.toscrape.com/"]
def parse(self, response):
pass
می توانید مشاهده کنید که کد بسیار محدودی دارد و چیزهای زیادی برای نوشتن توسط توسعه دهنده باقی مانده است. و حتما ملاحظه کرده اید که این کد با استفاده از آن ایجاد شده است پایه ای الگوی خراشیده “عنکبوت “نقل قول” را با استفاده از الگوی “basic” در ماژول ایجاد کرد:”. بنابراین، بعداً ما از همان رویکرد استفاده خواهیم کرد، اما از الگوی خودمان پر شده با کدهای بیشتر مخصوص کار خراش دادن خود استفاده خواهیم کرد، بنابراین به حداقل تغییرات نیاز خواهیم داشت تا عنکبوت برای منبع خاصی کار کند.
حالا، بیایید جلو برویم و اولین عنکبوت را برای خراش دادن نقل قول ها تکمیل کنیم. ما برای هر نقل قول تنها دو مقدار دریافت می کنیم: عنوان و نویسنده. بنابراین، پس از افزودن کد مورد نیاز، کد عنکبوتی مانند زیر به نظر می رسد.
import scrapy
class QuotesSpider(scrapy.Spider):
name = "Quotes"
allowed_domains = ["quotes.toscrape.com"]
start_urls = ["https://quotes.toscrape.com/"]
def parse(self, response):
#each quote is within
quotes = response.css("div.quote")
for quote in quotes:
#each quote text is within
title=quote.css("span.text::text").get()
#each author info is within
author =quote.css("small.author::text").get()
yield{
'title':title,
'author':author
}
You can download the code from the repo Link or copy from gist Link.
The above code is based on the understanding of html that is outcome of 'inspect' option in chrome. You can see the source of page in the below screenshot:

You can observe that each quote is under a
(blue rectangle) so we can get the html of all quotes by using "div.quote" selector and so the line quotes = response.css("div.quote")
will تمام نقل قول ها را ارائه می دهد و سپس در حلقه، می توانیم متن و نویسنده را برای هر نقل قول با استفاده از آن استخراج کنیم "span.text::text"
و "small.author::text"
انتخابگر به ترتیب. حتما متوجه شده اید "::متن" با عنوان و نویسنده در حالی که در نقل قول نیست، به این دلیل است که، ما فقط می خواهیم متن یعنی مقدار درون هر تگ.
هنگامی که عنکبوت شما آماده شد، می توانید عنکبوت خود را برای خراش دادن داده ها با استفاده از دستور scrapy crawl و فقط با ارسال نام عنکبوت به عنوان آرگومان یعنی نقل قول در مثال زیر اجرا کنید: (شما باید در پوشه پروژه scrapy باشید تا scrapy مسیر عنکبوت ها را بشناسد)
(scrapy-demo)$scrapy crawl Quotes
اگر خروجی زیر را در ترمینال خود مشاهده کردید:
2024-07-27 18:56:37 [scrapy.core.scraper] DEBUG: Scraped from
{'title': '“The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”', 'author': 'Albert Einstein'}
2024-07-27 18:56:37 [scrapy.core.scraper] DEBUG: Scraped from
{'title': '“It is our choices, Harry, that show what we truly are, far more than our abilities.”', 'author': 'J.K. Rowling'}
2024-07-27 18:56:37 [scrapy.core.scraper] DEBUG: Scraped from
{'title': '“There are only two ways to live your life. One is as though nothing is a miracle. The other is as though everything is a miracle.”', 'author': 'Albert Einstein'}
2024-07-27 18:56:37 [scrapy.core.scraper] DEBUG: Scraped from
{'title': '“The person, be it gentleman or lady, who has not pleasure in a good novel, must be intolerably
تبریک می گویم ! اولین عنکبوت شما آماده است و داده ها را خراش می دهد.
2) اجزای اسکراپی را پیش ببرید
*5. تست و ایجاد اجزای دیگر *
اکنون، ما یک عنکبوت اولیه برای خراش دادن نقل قول از منبع وب داده شده داریم. بیایید سیستم خراش دادن را با ایجاد سایر اجزای یک اسکراپر مانند اقلام، اقلام، خطوط لوله و غیره قوی تر کنیم.
5.1. موارد، **
مورد ** در scrapy نوعی ساختار برای داده هایی است که ما در حال خزیدن هستیم. اجرای موارد مختلف تمیز کردن و طرحواره در کل فرآیند خراش دادن و کمک به کاهش خطاها در خراش دادن داده ها بسیار مفید است.
فرآیند ایجاد آیتم بسیار آسان است. پوشه پروژه شما از قبل دارای یک است items.py
فایل (spiders_automation_demo/items.py)، بنابراین شما فقط باید یک کلاس (QuoteItem()) برای مورد خود اضافه کنید و می توانید با ارث بردن این کار را انجام دهید. scrapy.Item
کلاس این items.py
فایل برای Quotes.py
عنکبوت به شکل زیر خواهد بود: (# برای جزئیات بیشتر در مورد مورد، به مستندات مراجعه کنید)
#spiders_automation_demo/items.py
import scrapy
class QuoteItem(scrapy.Item):
title = scrapy.Field()
author = scrapy.Field()
شما می توانید نام کلاس مورد خود را هر چیزی، در مثالی که ما استفاده کرده ایم، بگذارید QuoteItem()
.
اکنون آیتم شما آماده است و برای استفاده از این آیتم در spider خود (Quotes.py)، باید تغییرات کمی در کد قبلی به شرح زیر انجام دهید:
import scrapy
from spiders_automation_demo.items import QuoteItem
class QuotesSpider(scrapy.Spider):
name = "Quotes"
allowed_domains = ["quotes.toscrape.com"]
start_urls = ["https://quotes.toscrape.com/"]
def parse(self, response):
#each quote is within
quotes = response.css("div.quote")
for quote in quotes:
#create your item object
quote_item = QuoteItem()
#each quote text is within
title=quote.css("span.text::text").get()
#each author info is within
author =quote.css("small.author::text").get()
#add your selector to your item
quote_item['title']=title
quote_item['author']= author
#yield your item
yield quote_item
You can observe that we have made following changes to previous spdier code:
import your item to the spider (note: the import path may change as per your project name)
from spiders_automation_demo.items import QuoteItem
Create an object of for your item
quote_item = QuoteItem()
Add your selector to the item (you can do it directly instead of using title and author variable like:
title=quote.css("span.text::text").get()
quote_item['title']=title
#the above two lines can be replaced by a single line
quote_item['title']=quote.css("span.text::text").get()
- آخرین تغییر، بهجای ویژگیهای فردی، شیء مورد را ارائه میکند.
yield quote_item
همین است. عنکبوت شما در حال حاضر از آیتم استفاده می کند و در مورد خراش دادن و نامگذاری داده ها در این فرآیند سختگیرانه تر است. برای آزمایش این، میتوانید «عنوان» را به «متن» در items.py تغییر دهید و spider را اجرا کنید. خطای زیر را خواهید دید:
KeyError: 'QuoteItem does not support field: title'
این خطا به خودی خود توضیح داده شده است، که در عنکبوت ما سعی می کنیم ارزش عنوان را بدست آوریم اما عنوانی در QuoteItem ما وجود ندارد. چنین بررسی هایی به کاهش خطا در پروژه خراش داده های بزرگ کمک می کند. بعداً همان آیتم def را خواهید دید. می تواند برای تمیز کردن داده ها یا اجرای طرحواره داده یا نظارت و غیره استفاده شود.
با استفاده از gist items.py و spider می توانید کدهای items.py و spider اصلاح شده را کپی کنید
*5.2. بارگذار آیتم *
لودر آیتم نوعی پردازش داده های خراشیده شده قبل از ذخیره آن است. به عنوان مثال، فرض کنید می خواهید همه نقل قول ها را با حروف عنوان یا بزرگ بخواهید یا هر کاراکتر خاصی را حذف کنید. می توانید این کار را پس از خراش دادن و ذخیره داده ها انجام دهید، با این حال، چنین پردازشی قبل از ذخیره سازی آسان تر است و itemLoader راه های کارآمد برای انجام آن را به طور منظم ارائه کنید.
حال سوال این است که چگونه استفاده کنیم itemLoader? سه مکان / ترتیب برای استفاده از آن وجود دارد:
- همراه با کد مورد (شما حتی می توانید منطق itemLoader و آیتم را با هم ادغام کنید) در فایل items.py.
- همراه با کد عنکبوتی در Quotes.py
- فایل خارجی در پروژه شما یعنی itemsloaders.py
برای پروژه کوچکتر گزینه اول یا دوم مشکلی ندارد اما برای پروژه بزرگتر بهتر است یک فایل خارجی برای itemLoader داشته باشید و از این روش استفاده می کنم.
بنابراین، فقط یک فایل پایتون در پروژه خود به همان سطح فایل items.py ایجاد کنید spiders_automation_demo/itemsloader.py
و کد زیر را اضافه کنید:
#spiders_automation_demo/itemsloader.py
#required imports
from scrapy.loader import ItemLoader
from scrapy.loader.processors import TakeFirst
#define your methods to apply on item value
def to_title_case(title):
return title.title()
#define your loader class
class QuoteLoader(ItemLoader):
default_output_processor = TakeFirst()
title_in = MapCompose(str.strip, to_title_case)
author_in = MapCompose(str.strip, to_title_case)
بنابراین، itemLoader شما آماده است و اکنون باید spider Quote.py خود را برای استفاده از itemloader تغییر دهید.
import scrapy
from spiders_automation_demo.items import QuoteItem
from spiders_automation_demo.itemsloader import QuoteLoader
class QuotesSpider(scrapy.Spider):
name = "Quotes"
allowed_domains = ["quotes.toscrape.com"]
start_urls = ["https://quotes.toscrape.com/"]
def parse(self, response):
#each quote is within
quotes = response.css("div.quote")
for quote in quotes:
#create your item object
#quote_item = QuoteItem()
#create your loader
loader = QuoteLoader(item=QuoteItem(), selector=quote)
#add your selector to your item
#each quote text is within
loader.add_css('title',"span.text::text")
#each author info is within
loader.add_css('author',"small.author::text")
#yield your item via the loader using .load_item()
yield loader.load_item()
import your itemloader to your spider
from scrapy.loader.processors import TakeFirst,MapCompose
create the loader object using your itemloader
loader = QuoteLoader(item=QuoteItem(), selector=quote)
Make changes with selector to use loader
loader.add_css('title',"span.text::text")
loader.add_css('author',"small.author::text")
- بازده خود را برای استفاده از لودر تغییر دهید
loader.load_item()
اکنون، عنکبوت به روز شده خود را اجرا و آزمایش کنید و مشاهده خواهید کرد که تمام متن های نقل قول در حروف عنوان هستند، به عنوان مثال: متن اصلی نقل قول
«سعی کنید مرد موفقی نشوید. بلکه تبدیل به یک مرد با ارزش شوید.»
به عنوان TitleCase تبدیل می شود
«سعی نکنید مرد موفقی شوید. در عوض مردی با ارزش شوید.»
5.3. خطوط لوله
ما در کار جمع آوری داده ها با عنکبوت ها پیشرفت کافی داشته ایم. حالا بیایید عنکبوت ها را برای فعال کردن به روز کنیم خطوط لوله در پروژه ما
گزینه Pipelines در Scrapy مکانی عالی برای انجام عملیات های مختلف پس از خراشیدن و بارگیری یک آیتم توسط آیتم لودر است. خطوط لوله می توانند سطح پیشرفته تری از تمیز کردن و پردازش داده ها را در طول فرآیند خراش دادن داده ها داشته باشند. به عنوان مثال، حذف یک مورد بر اساس هر شرایطی، مانند موارد تکراری (همان عنوان برای نقل قول) یا مقدار از دست رفته (بدون ارزش برای نویسنده). چنین الزاماتی را می توان از طریق خط لوله پیکربندی کرد. می توانید اطلاعات بیشتری در مورد خط لوله از سند اسکرپی در لینک بخوانید
برای مثال، میخواهم خط لولهای ایجاد کنم که فقط آن نقل قولهایی را که «عشق» یا «زندگی» در عنوان دارند، حفظ کنم، بنابراین اگر یکی از این دو کلمه در دسترس نباشد، آن نقل قول ذخیره یا پردازش نخواهد شد.
هر خط لوله ای را می توان در فایل pipelines.py در پروژه ایجاد کرد که به عنوان کد boilerplate پس از ایجاد پروژه ایجاد شد، یعنی (spiders_automation_demo/pipelines.py)
from scrapy.exceptions import DropItem
class FilterQuotesPipelineLoveOrLife:
def process_item(self, item, spider):
# Check if 'love' or 'life' is in the text
if 'love' in item['title'].lower() or 'life' in item['title'].lower():
return item
else:
raise DropItem(f"Quote without 'love' or 'life' in title text: {item['title']}")
کد خط لوله ساده است، شما باید یک کلاس برای یک خط لوله جداگانه ایجاد کنید FilterQuotesPipelineLoveOrLife
و منطق را در متد کلاس process_item() اضافه کنید.
خط لوله را فعال کنید: برخلاف آیتم یا بارگذار آیتم، خط لوله با وارد کردن آن به عنکبوت کار نمی کند. اما، شما باید خط لوله خود را در settings.py فعال کنید (دوباره، این فایل از قبل در پوشه پروژه شما وجود دارد و در طول فرآیند اولیه سازی پروژه ایجاد شده است). شما می توانید خط لوله جدید ایجاد شده خود را به صورت زیر اضافه کنید (بخش نظر داده شده را در settings.py بیابید و بر اساس آن اصلاح کنید:
# Enable the custom pipeline
ITEM_PIPELINES = {
'spiders_automation_demo.pipelines.FilterQuotesPipelineLoveOrLife': 300,
}
این همه است، خط لوله شما برای فیلتر کردن متن نقل قول با «عشق» یا «زندگی» آماده است و نیازی به تغییر عنکبوت قبلی خود ندارید. می توانید عنکبوت را اجرا کنید و خط لوله خود را آزمایش کنید. در Scrapy log زیر را مشاهده خواهید کرد "هشدار" پیام (و اگر داده های خود را ذخیره کنید، می بینید که فقط دو نقل قول ذخیره شده است.):
هشدار: حذف شد: نقل قول بدون «عشق» یا «زندگی» در متن عنوان: «این انتخابهای ما هستند، هری، آنچه را که واقعاً هستیم، بسیار بیشتر از تواناییهایمان نشان میدهند».
{'نویسنده': 'جی کی رولینگ'،
'title': '"این انتخاب های ما هستند، هری، که نشان می دهد ما واقعا چه هستیم، خیلی بیشتر"
"از توانایی های ما."}
5.4. تغذیه می کند
تا به حال، ما شاهد اجرای خروجی عنکبوت خود در ترمینال بودهایم و این فقط در هنگام آزمایش خوب است، اما در یک پروژه واقعی باید دادههای خزیده شده/خراششده را ذخیره کنید.
ابزار Scrapy به پارامتر / آرگومان (-o یا -O) اجازه می دهد تا نام فایل را برای ذخیره خروجی به فایل مشخص شده از طریق خط فرمان، مانند:
$scrapy crawl quotes -o quotes.json
$scrapy crawl quotes -O quotes.json
با -o و -O تفاوت وجود دارد (یعنی حروف کوچک و بزرگ)
- '-o': داده ها را در صورت وجود به فایل اضافه می کند
- '-O': فایل را در صورت وجود بازنویسی می کند.
با این حال، در پروژههای واقعی، ما میخواهیم نام فایل، مسیر و نوع فایل را به روشهای بهتری مشخص کنیم تا نظارت و نگهداری آن آسان باشد. Scrapy راه آسانی را برای دستیابی به آن با پیکربندی فراهم می کند تغذیه در settings.py (شبیه به پیکربندی خط لوله). باید فرهنگ لغت پایتون زیر را به settings.py اضافه کنید و با ذخیره کردن آن به صورت مشخص شده، داده های خراشیده شده را پایدار می کند.
ما از نام عنکبوت برای ذخیره داده های خراشیده شده استفاده می کنیم (به فکر ردیابی داده ها توسط عنکبوت ها) و امکان بازنویسی اگر نام فایل از قبل وجود داشته باشد (مشابه آرگومان -O از طریق خط فرمان).
FEEDS = {
'%(name)s_quotes.json': {
'format': 'json',
'overwrite': True,
},
}
توضیح
- %(name)s_quotes.json: از نام عنکبوت به عنوان پیشوند فایل خروجی استفاده می کند.
- format: 'json': مشخص می کند که فرمت خروجی JSON باشد.
- overwrite: True: اطمینان حاصل می کند که اگر فایل از قبل وجود داشته باشد، رونویسی شده است.
حال، اگر عنکبوت خود را در انتها اجرا کنید، یک فایل json ایجاد میشود (Quotes_quotes.json) و تمام نقل قولهای خراشیده و فیلتر شده خواهد بود. مانند:
[
{
"title": "“There Are Only Two Ways To Live Your Life. One Is As Though Nothing Is A Miracle. The Other Is As Though Everything Is A Miracle.”",
"author": "Albert Einstein"
},
{
"title": "“It Is Better To Be Hated For What You Are Than To Be Loved For What You Are Not.”",
"author": "André Gide"
}
]
5.5. تنظیمات
در حال حاضر، شما قبلاً از settings.py برای خط لوله و فیدها استفاده کردهاید، با این حال پیکربندیهای بیشتری وجود دارد که میتوان آنها را از طریق settings.py تنظیم یا لغو تنظیم کرد و بر اساس پروژه اعمال میشود. بنابراین، شما همچنین می توانید با استفاده از گزینه custom_settings، تنظیماتی را برای عنکبوت در کد عنکبوتی ایجاد کنید. با این حال، ما قرار نیست از این برای این نسخه ی نمایشی استفاده کنیم. شما می توانید خودتان را کشف کنید.
اگر settings.py را باز کرده باشید، به طور پیشفرض گزینههای فعالسازی زیادی را میبینید. مانند:
BOT_NAME = "spiders_automation_demo"
SPIDER_MODULES = ["spiders_automation_demo.spiders"]
NEWSPIDER_MODULE = "spiders_automation_demo.spiders"
# Obey robots.txt rules
ROBOTSTXT_OBEY = True
ما با sandbox یا وب سایت منبع ساختگی کار می کنیم، بنابراین نیازی به انجام تنظیمات زیادی از جمله ROBOTSTXT_OBEY نداریم، بسیاری از سایت ها اجازه خزیدن را نمی دهند و با استفاده از فایل robot.txt اطلاع رسانی می شود، بنابراین اگر ROBOTSTXT_OBEY=True باشد، scrapy آن را پاک نمی کند. اگر میخواهید خزیدن را اعمال کنید، میتوانید آن را نادرست تنظیم کنید (ROBOTSTXT_OBEY=True).
robots.txt یک کنوانسیون است، بنابراین به خودی خود دست از خراش نمی کشد، بلکه فقط یک رویکرد اخلاقی برای احترام به robots.txt است.
3) اتوماسیون عنکبوت
اکنون پروژه خراش دادن شما با 1 عنکبوت با سایر اجزای مورد نیاز آماده است. بنابراین، اکنون بیایید به درک فرآیند اتوماسیون و نحوه ایجاد عنکبوت ها برای خراش دادن نقل قول از منابع دیگر مانند سایر سایت های ساختگی حرکت کنیم:
فرآیند دستی:
اجازه دهید ابتدا روند دستی را طی کنیم. شما دو گزینه دارید:
- با استفاده از scrapy genspider یک عنکبوت جدید ایجاد کنید و روش تجزیه را کپی کنید
$scrapy genspider QuotesAjitSource https://quotes-scrape.netlify.app/
import scrapy
class QuoteajitsourceSpider(scrapy.Spider):
name = "QuotesAjitSource"
allowed_domains = ["quotes-scrape.netlify.app"]
start_urls = ["https://quotes-scrape.netlify.app/"]
def parse(self, response):
pass
- یک فایل پایتون ایجاد کنید و کد پیست را از عنکبوت قبلی کپی کنید
در هر دو روش، شما کد را برای عنکبوت جدید یعنی برای هر منبع جدید کپی، پیست و اصلاح می کنید. و اگر به خاطر داشته باشید، ما با مشکل یک پروژه خراش دادن با بیش از 1000 منبع شروع کردیم.
بیایید روند دستی را مانند منبع قبلی دنبال کنیم. استفاده کنید بازرسی گزینه ها در کروم

##spiders_automation_demo/spiders/QuotesAjitSource.py
import scrapy
from spiders_automation_demo.items import QuoteItem
from spiders_automation_demo.itemsloader import QuoteLoader
class QuoteajitsourceSpider(scrapy.Spider):
name = "QuotesAjitSource"
allowed_domains = ["quotes-scrape.netlify.app"]
start_urls = ["https://quotes-scrape.netlify.app/"]
def parse(self, response):
#each quote is within
quotes = response.css("div.quote-container")
for quote in quotes:
#create your item object
#quote_item = QuoteItem()
#create your loader
loader = QuoteLoader(item=QuoteItem(), selector=quote)
#add your selector to your item
#each quote text is within
loader.add_css('title',"h2.title::text")
#each author info is within
loader.add_css('author',"p.author::text")
#yield your item via the loader using .load_item()
yield loader.load_item()
The output json file will be empty because there are not quotes with 'love' or 'life' word in it. So, let's modify our filter pipeline and add 'work' to it.
from scrapy.exceptions import DropItem
class FilterQuotesPipelineLoveOrLife:
def process_item(self, item, spider):
# Check if 'love' or 'life' is in the text
if 'love' in item['title'].lower() or 'life' in item['title'].lower() or 'work' in item['title'].lower():
return item
else:
raise DropItem(f"Quote without 'love' or 'life' or 'work' in title text: {item['title']}")
اکنون فایل json خروجی خود را باز کنید و نقل قول های زیر را خواهید داشت:
[
{
"title": "If I Find 10,000 Ways Something Won'T Work, I Haven'T Failed. I Am Not Discouraged, Because Every Wrong Attempt Discarded Is Another Step Forward.",
"author": "— Thomas Edison"
},
{
"title": "As A Cure For Worrying, Work Is Better Than Whisky.",
"author": "— Thomas Edison"
}
]
اکنون، شما دو عنکبوت دارید، پس بیایید بررسی کنیم که تفاوت بین این عنکبوت ها چیست. ما از ابزارهای diff برای برجسته کردن تفاوت بین این دو عنکبوت استفاده کرده ایم. از طریق لینک هم میتونید چک کنید

اگر تفاوت کد عنکبوت را مشاهده کنید، موارد زیر را متوجه خواهید شد:
- مقادیر / فراداده خاص عنکبوت
- نام کلاس عنکبوت
- نام عنکبوت
- مقدار در مجاز_دامنه ها
-
مقدار در start_urls
-
مقادیر خاص منبع، عمدتاً ارزش انتخابگرها
- مقدار انتخابگر برای div اصلی که نقل قول فردی را نگه می دارد
- مقدار انتخابگر برای عنوان حاوی متن عنوان نقل قول فردی
- مقدار انتخابگر برای نویسنده ای که متن نویسنده نقل قول فردی را نگه می دارد
فرآیند خودکار: استفاده از قالب برای spdier و json
1. یک فایل json ایجاد کنید
یک فایل json ایجاد کنید که در آن هر یک از ویژگی های آیتم (به عنوان مثال: عنوان و نویسنده) کلید و انتخابگر (div.title) برای آنها مقدار باشد. و همچنین شامل اطلاعات منبع مانند نام سایت، آدرسهای اینترنتی که میتوان از آنها برای ایجاد کلاس عنکبوت استفاده کرد.
{
"spidername": "Quotes Ajit Source2",
"start_urls": ["https://quotes-scrape.netlify.app/"],
"quote_div_main": "div.quote-container",
"title_selector": "h2.title",
"author_selector": "p.author"
}
2. یک فایل قالب ایجاد کنید
ما به الگوی Jinja2 (مستندات) می رویم، بنابراین اجازه دهید با هر کد عنکبوتی شروع کنیم و آن را تغییر دهیم تا قالب Jinja2 را اتخاذ کند.
#spiders_automation_demo/templates/spiders/quotespider_template.jinja2
import scrapy
from spiders_automation_demo.items import QuoteItem
from spiders_automation_demo.itemsloader import QuoteLoader
class {{ spiderclass}}(scrapy.Spider):
name = "{{spidername}}"
allowed_domains = ["{{allowed_domains}}"]
start_urls = {{start_urls}}
def parse(self, response):
#each quote is within
quotes = response.css("{{quote_div_main}}")
for quote in quotes:
#create your item object
#quote_item = QuoteItem()
#create your loader
loader = QuoteLoader(item=QuoteItem(), selector=quote)
#add your selector to your item
#each quote text is within
loader.add_css('title',"{{title_selector}}::text")
#each author info is within
loader.add_css('author',"{{author_selector}}::text")
#yield your item via the loader using .load_item()
yield loader.load_item()
3. Create python script to generate spider( using template and json file created in previous stop)
#bluk_gen_spiders.py
import json
from jinja2 import Environment, FileSystemLoader
from urllib.parse import urlparse
import os
# Load JSON configuration
with open('sources.json') as f:
sources = json.load(f)
# Set up Jinja2 environment
env = Environment(loader=FileSystemLoader('spiders_automation_demo/templates/spiders/'))
template = env.get_template('quotespider_template.jinja2')
# Folder where you want to save the spider file
folder_name = 'spiders_automation_demo/spiders'
for config in sources:
# Extract values and manipulate strings
spidername = config['spidername'].title().replace(" ", "")
spiderclass = spidername.capitalize()+'Spider'
start_urls = config['start_urls']
parsed_url = urlparse(start_urls[0])
allowed_domains = parsed_url.netloc
# Render the template with values
output = template.render(
spiderclass=spiderclass,
spidername=spidername,
allowed_domains=allowed_domains,
start_urls=start_urls,
quote_div_main=config['quote_div_main'],
title_selector=config['title_selector'],
author_selector=config['author_selector']
)
# Ensure the folder exists
os.makedirs(folder_name, exist_ok=True)
# Save the rendered template to a new Python file in the specified folder
file_path = os.path.join(folder_name, f'{spiderclass}.py')
with open(file_path, 'w') as f:
f.write(output)
print(f"Spider generated: {file_path}")
تعیین مسیر مناسب برای نگهداری عنکبوت ها (folder_name="spiders_automation_demo/spiders"
) و مسیر قالب (env = Environment(loader=FileSystemLoader('spiders_automation_demo/templates/spiders/'))
) و json و اسکریپت خود را اجرا کنید. مثلا:
(scrapy-demo)$python bluk_gen_spiders.py
اگر همه چیز خوب باشد، برای همه منابع اضافه شده در زیر پوشه spiders پروژه، عنکبوت خواهید داشت. (در مکان اسکریپت دقت کنید)
اکنون، می توانید 1-2 عنکبوت ایجاد شده توسط اسکریپت نسل را اجرا و آزمایش کنید و در صورت مشکل، آن را برطرف کنید (چه در اسکریپت نسل یا در فایل قالب) و می توانید اسکریپت را دوباره اجرا کنید.
اکنون، از روی کنجکاوی، فقط به کد spider Manual در مقابل ایجاد شده توسط اسکریپت با استفاده از الگو و json نگاهی بیندازید. پیوند تفاوت می توانید متوجه شوید که هیچ تفاوتی در کد وجود ندارد (نقل قول های تکی و دوگانه در starts_url نیز قابل رفع هستند :))

تبریک می گویم !! شما ایجاد عنکبوتها را خودکار کردهاید و میتوانید فقط با اضافه کردن پنج مقدار در دستهها، عنکبوتها را برای منابع جدید اضافه کنید. sources.json.
به عنوان مثال، اگر دو منبع دیگر برای نقل قول ها پیدا کردید و می خواهید برای هر کدام عنکبوت اضافه کنید:
1) آدرس اینترنتی نقل قول مغزی
2) نقل قول های AZ [URL]
سپس، شما فقط باید صفحات وب مربوطه را بررسی کنید و فایل sources.json را به صورت زیر تغییر دهید:
[
{
"spidername": "Quote Ajit Source",
"start_urls": ["https://quotes-scrape.netlify.app/"],
"quote_div_main": "div.quote-container",
"title_selector": "h2.title",
"author_selector": "p.author"
},
{
"spidername": "Brainy Quote",
"start_urls": ["https://www.brainyquote.com/topics/life-quotes"],
"quote_div_main": "div.grid-item.qb.clearfix.bqQt",
"title_selector": "div",
"author_selector": "a.bq-aut.qa_109542.oncl_a"
},
{
"spidername": "AZ Quotes",
"start_urls": ["https://www.azquotes.com/quotes/topics/life.html"],
"quote_div_main": "div.wrap-block",
"title_selector": "p a.title",
"author_selector": "div.author a"
}
]
اکنون، اسکریپت تولید عنکبوت خود را مجدداً به صورت زیر اجرا کنید و اکنون سه عنکبوت جدید ایجاد خواهید کرد (شما می توانید کدی را اضافه کنید تا عنکبوت ایجاد نشود اگر نام قبلاً وجود دارد).
(scrapy-demo)$python bluk_gen_spiders.py
توجه: با این حال، عنکبوت جدید ایجاد شده برای Brainy Quote یک خطای 403 (محدودیت خزیدن) می دهد، بنابراین داده ها نمی توانند با تنظیمات فعلی خراشیده شوند و دور زدن محدودیت موضوع دیگری برای چند روز دیگر است.
شما spider را برای نقل قول های AZ اجرا می کنید و داده های زیر را در فایل json دریافت خواهید کرد (AzQuotes_quotes.json):
(scrapy-demo)$scrapy crawl AzQuotes
[
{
"title": "The Happiness Of Your Life Depends Upon The Quality Of Your Thoughts.",
"author": "Marcus Aurelius"
},
{
"title": "Without Forgiveness Life Is Governed By... An Endless Cycle Of Resentment And Retaliation.",
"author": "Roberto Assagioli"
},
{
"title": "The Tragedy Of Life Is What Dies Inside A Man While He Lives.",
"author": "Albert Schweitzer"
},
......truncated
]
توجه: مقاله در وضعیت بازبینی قرار دارد بنابراین ممکن است اشتباهات تایپی، گرامری و خطاهای فنی وجود داشته باشد. بنابراین، در صورت مشاهده هرگونه خطای فنی، از طریق نظر به من اطلاع دهید، بنابراین در نسخه اصلاح شده آن را برطرف خواهم کرد.
در ادامه بخوانید

پایتون بهتر از جاوا اسکریپت است!
مایا رامکیشون -

پایتون: از مبتدی تا حرفه ای در 30 دقیقه (قسمت 1)
اسکافیلد آیدهن -

خراش دادن نظرات توییتر با سلنیوم (پایتون): راهنمای گام به گام
دیوید هرناندز تورس -

کار با پایگاه داده در جنگو با استفاده از PostgreSQL
شیطون -