MongoDB -ו Scrapy םע טנרטניא דוריג


Scrapy לש הקזח טנרטניא דוריג תרגסמ איה Python ב שמתשהל לוכי ה

דציכ דמלת ,הז ךירדמב:

  • טקיורפ רדגהו רדגה
  • Scrapy םע תילנויצקנופ טנרטניא תדרגמ ונב
  • םינותנ ץלח תועצמאב םירתאמ םיררוב
  • ןסחא לש םינותנ דסמב םידרוגמ םינותנ MongoDB
  • קודב וםיגאב יופינ לש טנרטניאה דרגמ תא Scrapy

.תושקבו הפי קרמב שומישהמ הלדג ךלש טקיורפה לש תובכרומה לבא ,רבעב םירתא תדריג םא

.CSS-ו HTML ריכהלו ישילש דצ לש תוליבח םע תוחונב דובעל ,םימצע החנומ תונכת ןיבהל

.רתוי הברה קימעהל ךל םירשפאמה םיישומיש םילכ המכ ריכתו ,טנרטניאהמ םייטטס םינותנ

דרגמה ימוגיפ תא ןכה

.ךלש הדירגה תומישמל הרדשה דומע שמשיש יסיסב טקיורפ הנבמ תריציו םישורדה םילכה תר

:(הניעט ,היצמרופסנרט ,ץוליח) ETL ךילהתכ וילא תוסחייתה ךות ,םלש טנרטניא דוריג ט

  • ץלח שיבכע תועצמאב רתאהמ םינותנ Scrapy ךלש טנרטניאה קרוסכ.
  • ךופה טירפ רוניצ תועצמאב ,םהלש תומיא וא יוקינ ידי לע לשמל ,הלא
  • ןעט ומכ ןוסחא תכרעמל היצמרופסנרט ורבעש םינותנה תא MongoDB םיט

Scrapy ש קזחה הנבמה תובקעב םירתא דוריג דומלל ידכ הזה םוגיפב שמתשתו ,וללה םיכיל

.םיעוציב לעב טנרטניא דרגמ תיינבב ךישמהל בטיה דיוצמ התאש חיטבהל ידכ תיטמוטוא רצ

Scrapy-ה תליבח תא ןקתה

:Scrapy תא ןיקתהל לכות ,ןכמ רחאל .ךלש תילבולגה Python תנקתהמ תדרפנ הנקתהה לע ר

(venv) $ python -m pip install scrapy

:טלפה תגצהו scrapy הדוקפה תלעפה ידי לע התוא תמאל לכות ,הנקתהה תמל

(venv) $ scrapy
Scrapy 2.11.2 - no active project

Usage:
  scrapy <command> [options] [args]

Available commands:
  bench         Run quick benchmark test
  fetch         Fetch a URL using the Scrapy downloader
  genspider     Generate new spider using pre-defined templates
  runspider     Run a self-contained spider (without creating a project)
  settings      Get settings values
  shell         Interactive scraping console
  startproject  Create new project
  version       Print Scrapy version
  view          Open URL in browser, as seen by Scrapy

  [ more ]      More commands available when run from project directory

Use "scrapy <command> -h" to see more info about a command

.טקיורפ רוציל ידכ startproject תשגדומה הדוקפה תא ליעפת ןכמ רחאל .

Scrapy טקיורפ רוצ

Scrapy ביבס היונב םיטקיורפ. םשב רתא דוריג לע ודבעת ,הז ךירדמב

:שדח טקיורפ תריציל הדוקפ תקפסמ תרגסמה ,הרזעה טסקטב תיהיז רבכ ילואש יפכ

(venv) $ scrapy startproject books

.וז םע וז הבוט היצקארטניא םייקל תולוכיש תורגוב תורגסמ יתש ןה Django-ו Scrapy-ו

:תיטמוטוא ורצונש תוירפסו םיצבק רפסמ ליכמה טקיורפ הנבמ םע ךתוא רידגמש books

books/
│
├── books/
│   │
│   ├── spiders/
│   │   └── __init__.py
│   │
│   ├── __init__.py
│   ├── items.py
│   ├── middlewares.py
│   ├── pipelines.py
│   └── settings.py
│
└── scrapy.cfg

Scrapy טקיורפ ןוגראב ךל רוזעי אוהו ,הזה הנבמה לע ךמתסמ Scrapy טנרטניא דוריג טק

  • books/ ה טקיורפ לש סיסבה תיירפס איה-Scrapy ךלש.
  • books/spiders/ ךלש שיבכעה תורדגה ןוסחאל היירפס א
  • books/items.py ודרגש םיטירפה לש םינותנה הנבמ תרד
  • books/middlewares.py ךלש תישיא תומאתומה םייניבה
  • books/pipelines.py םיטירפ דוביעל תורוניצ תרדגהל
  • books/settings.py ךלש טקיורפה תרדגהל תורדגהה ץבו

.עדימ ץלחל הצרת ונממש רוקמה רתאב לכתסת תעכ ,ךלש טקיורפה ימוגיפ תרדגה םע .ךלש ת

דרגל הצור התאש רוקמה תא קודב

.ביבסמ ץוחללו רתאל טוונל ,ןפדפדה תא חותפל איה טנרטניא רתא קודבל רתויב הריהמה ך

ךלש ןפדפדב רתאב ןייע

.ךלש ןפדפדה לש םינבומה םיחתפמה ילכ תועצמאב רתויב הבוטה הרוצב תאז תושעל לוכי הת

:ןלהל גצומש הזל המוד הארייש קשממ הארת ,רפס טירפ תיהיזו ךלש ןפדפדב םיחתפמה ילכ

:רפס לכמ םינותנ תודוקנ שולש ץלחל הצרת .דרגל ךנוצרבש עדימ תסיפ לכ רובע םיידוחיי

  1. תרֶתֶוֹכּ
  2. ריחִמְ
  3. רתא תבותכ

:םיטנמלאהמ דחא לכ רובע םיאבה םיכרעה תא לבקל רומא התא ,רתאב ןושארה רפסה רובע CS

Title

#default > div > div > div > div > section > div:nth-child(2) > ol > li:

Price

#default > div > div > div > div > section > div:nth-child(2) > ol > li:

URL

#default > div > div > div > div > section > div:nth-child(2) > ol > li:

.HTML-ה ךמסמ לש שרושה טנמלאב םיליחתמש םיטלחומ םיביתנ םהש ללגב הז .ןפוא ותואב ם

:<article> הזה טנמלאה תא ההיזו ךלש ןפדפדה לא רוזח .

<article class="product_pod">
  <div class="image_container">
    <a href="catalogue/a-light-in-the-attic_1000/index.html"><img
        src="media/cache/2c/da/2cdad67c44b002e7ead0cc35693c0e8b.jpg"
        alt="A Light in the Attic" class="thumbnail"></a>
  </div>
  <p class="star-rating Three">
    <i class="icon-star"></i>
    <i class="icon-star"></i>
    <i class="icon-star"></i>
    <i class="icon-star"></i>
    <i class="icon-star"></i>
  </p>
  <h3><a href="catalogue/a-light-in-the-attic_1000/index.html"
      title="A Light in the Attic">A Light in the ...</a></h3>
  <div class="product_price">
    <p class="price_color">£51.77</p>
    <p class="instock availability">
      <i class="icon-ok"></i>
      In stock
    </p>
    <form>
      <button type="submit" class="btn btn-primary btn-block"
        data-loading-text="Adding...">Add to basket</button>
    </form>
  </div>
</article>

!product_pod ,הקלחמ םש שי וליפא הזה טנמלאלו - ולש

.הברהב םירצק םיררוב םע יטנוולרה עדימה תא ץלחלו ,הלא לכ לע האלולב רובעל לכות ןכ

.דועו ,הז תא קוידב תושעל ידכ Scrapy לש תינבומה תפטעמה םע דובעל לוכי התא !שי ןכ

Scrapy-ה תפטעמ םע םינותנה לש המידקמ הגוצת

.שפחמ התאש םיטנמלאה תא ןוכנ םידקממ םהש חיטבהל ידכ CSS יררובו XPath ייוטיב םע י

:רתאה לש רתאה תבותכ הירחאו shell הדוקפב שומיש ידי לע דרגל ךנוצרבש

(venv) $ scrapy shell http://books.toscrape.com

.דעיה רתא לש HTML-ה ןכותלו Scrapy יטקייבואל השיג םע לבא ,יביטקארטניא Python RE

:שומיש תוארוה םהירחאו םינמוי המכ הארת ,וזה הדוקפה תא ליעפמ התא רשאכ

...
[s] Available Scrapy objects:
[s]   scrapy     scrapy module (contains scrapy.Request, scrapy.Selector, etc)
[s]   crawler    <scrapy.crawler.Crawler object at 0x1070dcd40>
[s]   item       {}
[s]   request    <GET https://books.toscrape.com/>
[s]   response   <200 https://books.toscrape.com/>
[s]   settings   <scrapy.settings.Settings object at 0x10727ac90>
[s]   spider     <BookSpider 'book' at 0x107756990>
[s] Useful shortcuts:
[s]   fetch(url[, redirect=True]) Fetch URL and update local objects (by default, redirects are followed)
[s]   fetch(req)                  Fetch a scrapy.Request and update local objects
[s]   shelp()           Shell help (print this help)
[s]   view(response)    View response in a browser
>>>

.ץלחל הצרת ילואש םינותנה תקידבל רתויב הבושחה איה response רשאכ ,ש

:ךלש ןפדפדה לש םיחתפמה ילכ תועצמאב רבעב תישע ובש ןפואל המודב ףדה תא קודבל ךל ת

  • .url ףדה לש רתאה תבותכ תא ליכמ.
  • .status ה בצמ דוק תא ךל גיצמ-HTTP הבוגתה לש.
  • .headers ה תורתוכ לכ תא גיצמ-HTTP הבוגתה לש.
  • .body הבוגתה לש םיימלוגה םיתבה תא ליכמ.
  • .text תזורחמכ הבוגתה לש חנעופמה טסקטה תא ליכמ Unicode.

:האבה הדוקפה תא ליעפהל לוכי התא ,הבוגתה לש HTTP-ה בצמ דוק תא קודבל ידכ ,המגודל

>>> response.status
200

:.text-ב שמתשהל לוכי התא ,ףדה לש HTML-ה ןכות תא גיצהל ידכ .דרגל ך

>>> response.text
'<!DOCTYPE html>\n<!--[if lt IE 7]>
...

.םייפיצפס םיטנמלאל דקמל ידכ CSS יררובב וא XPath ייוטיבב שמתשהל רתוי ישעמ ןכלו

Scrapy תיירפסב שמתשמ Parsel ייוטיבב לפטל ידכ XPath יררובבו CSS. Parsel הקלחמ ת

>>> from parsel import Selector

>>> html = "<html><body><h1>Hello, world!</h1></body></html>"
>>> selector = Selector(text=html)
>>> text = selector.xpath("//h1/text()").get()
>>> text
'Hello, world!'

.response טקייבואה תא חתנל ידכ Scrapy ךותב Parsel יררוב םתואב שמת

.טנרטניא חותיפ םתרקח םא רתוי ךל םירכומ ויהי הארנכ CSS יררוב לבא ,תאז םוקמב XPa

:הקתעה תועצמאב יתאצמ 'התאש ךוראה CSS-ה ררוב לש יטנוולרה קלחה קר תועצמאב רפס תר

>>> all_book_elements = response.css("article.product_pod")

>>> for book in all_book_elements:
...     print(book.css("h3 > a::attr(title)").get())
...
A Light in the Attic
Tipping the Velvet
Soumission
(...)

.תזורחמכ תואצותה לש הנושארה המאתהה תא לבקמ התא ,לבקתמה Selector

.ךלש ףוסמל םירפסה תורתוכ לכ תא החלצהב סיפדהל ידכ וז השיגב שמתשהל לוכי התא

:המוד ןפואב םיריחמה תאו םירתאה תובותכ תא דקמ ,תעכ .רצוקמ CSS ררוב םע םירפסה תו

>>> for book in all_book_elements:
...     print(book.css("h3 > a::attr(href)").get())
...
catalogue/a-light-in-the-attic_1000/index.html
catalogue/tipping-the-velvet_999/index.html
catalogue/soumission_998/index.html
(...)

>>> for book in all_book_elements:
...     print(book.css(".price_color::text").get())
...
£51.77
£53.74
£50.10
(...)

:םינוכנה םיטנמלאה תא דקמל ידכ תשמתשה םהבש CSS ריבחתמ םיגשומה תא לוקש ,ךלש שיבכ

h3 and a

HTML ביכר לש הז גוסמ םיביכרל דקממ

>

ןב טנמלא ןייצמ

.price_color and article.product_pod

הקלחמה םש תויהל ךירצ ביכר הזיאב ןייצמ ,ילנויצפוא ןפואבו הקלחמ םש ןייצמ

::text

HTML גת לש טסקטה ןכותל דקממ

::attr(href)

href הנוכתב רתאה תבותכ הז הרקמב ,HTML תנוכת לש ךרעל דקממ

:שפחמ התאש עדימה לכל השיג ךל תתל םילוכיש רתוי םירצק CSS יררוב תרשיאו תיהיז ,הז

Book elements

article.product_pod

URL

h3 > a::attr(href)

Title

h3 > a::attr(title)

Price

.price_color::text

.ךלש שיבכעה תביתכ תעב רצק ןמז ךות םהב שמתשת התא יכ הביבסב הלאה םיררובה תא רומש

.הדירגה ךילהתב תויועט התיחפמו ןמז תכסוח וז תיביטקארטניא השיג .לעופב שיבכעה דוק

Scrapy םע ךלש Web Scraper-ה תא הנב

.ךלש שיבכעה תא תונבל ןמזה עיגה ,ךלש Scrapy-ה טקיורפ תא החלצהב תרציו םירתא קודב

.םידומע יבורמ םינותנ יכרעמ רובעל ידכ דומיעב לופיטו ,ץלחל םכנוצרבש םיטנמלאה תא

טירפב םינותנה תא ףוסא

Item ןותייפ ןולימ םע השוע תייהש ךיאל המודב םיכרע תוצקהל לוכי התאש

טירפ תרדגה .הרדיסו תומיא ןוגכ ,טנרטניא דוריג רובע תוישומישש תופסו

.לוהינל תנתינו הייקנ הרוצב םינותנה הנבמ תא ןייצל ךל תרשפאמ וז השיג .scra

:רפס לכ לש ריחמהו תרתוכה ,רתאה תבותכ רובע תודש םע הרצונש BooksItem

import scrapy

class BooksItem(scrapy.Item):
    url = scrapy.Field()
    title = scrapy.Field()
    price = scrapy.Field()

.ליכי טירפש תודשה תא רידגהל ידכ וב שמתשהל לכותש ךכ טירפ

.דעיה רתאמ םיריחמו םירפס תורתוכ ,םירתא תובותכ אוצמל םכלש שיבכעל רוזעל ידכ תפטע

Scrapy לש שיבכע בותכ

:ךלש ןושארה שיבכעה תריציל הדוקפה תא לעפה ןכמ רחאלו ,books/ םשב ךל

(venv) $ cd books/
(venv) $ scrapy genspider book https://books.toscrape.com/
Created spider 'book' using template 'basic' in module:
  books.spiders.book

.ךלש יפיצפסה עדימה םע תעכ ךורעתש םיפסונ םימוגיפ המכ םג ללוכ הז .ךלש הרקמב < co

:עדימ תוסיפ יתש דוע קפסל ךירצ אוהו םש שי יסיסב שיבכע לכל

  1. דרגל ליחתהל הפיא
  2. הבוגתה תא חתנל דציכ

.genspider תועצמאב שיבכעה ימוגיפ תא תרדגה רשאכ ,שיבכעה םש תאו ,הז

:םינותנה תא ףוסאל ידכ BooksItem-ב שמתשהל ןכמ רחאלו ,הבוגתהמ עדימה

import scrapy

from books.items import BooksItem

class BookSpider(scrapy.Spider):
    name = "book"
    allowed_domains = ["books.toscrape.com"]
    start_urls = ["https://books.toscrape.com/"]

    def parse(self, response):
        for book in response.css("article.product_pod"):
            item = BooksItem()
            item["url"] = book.css("h3 > a::attr(href)").get()
            item["title"] = book.css("h3 > a::attr(title)").get()
            item["price"] = book.css(".price_color::text").get()
            yield item

.טירפ לכ רוציל ידכ האושת-ב תשמתשה ,ףוסבל .ןולימ ריבחת תועצמאב תיש

.טירפה רוניצל טירפה עפומ תא בינמ ןכמ רחאלו ךלש BooksItem לש םימיא

.םהמ דחא לכ רובע תיטמוטוא ול ארקת תרגסמה יזא ,start_urls רפסמ ללו

.טנרטניאהמ םינותנ איבהל ידכ ותוא חולשל לוכי התא ,הנבנש שדחה תשרב תוחונב בשייתה

רתאהמ םינותנ ץוליח

:crawl הדוקפה תועצמאב םשמ שיבכעה תא ליעפהל לוכי התא .ךלש Scrapy ט

(venv) $ scrapy crawl book

Scrapy םיספדומ התיחנה ףדב רפס לכ רובע וצלוחש םינותנה תא םג תוארל רומא התא ,םינ

2024-08-28 10:26:48 [scrapy.utils.log] INFO: Scrapy 2.11.2 started (bot: books)
...
{'price': '£51.77',
 'title': 'A Light in the Attic',
 'url': 'catalogue/a-light-in-the-attic_1000/index.html'}
2024-08-28 10:26:50 [scrapy.core.scraper] DEBUG: Scraped from <200 https://books.toscrape.com/>
{'price': '£53.74',
 'title': 'Tipping the Velvet',
 'url': 'catalogue/tipping-the-velvet_999/index.html'}
2024-08-28 10:26:50 [scrapy.core.scraper] DEBUG: Scraped from <200 https://books.toscrape.com/>
...
2024-08-28 10:26:50 [scrapy.core.engine] INFO: Spider closed (finished)

.םיבר ינמ דחא דומע קר הז ,תאז םע !המדה םירפסה תונח לש ןושארה דומעהמ ריחמהו תרת

!תרגסמב תינבומ רבכש רתוי הרישיו הקזח ךרד שי ,גאדת לא .םינימזה םיפדה לכ לע רוזח

םירתא תובותכ רחא בוקעו ןודיעב לפט

.יוארכ ךלש דעיה רתא תא קורסלו דומיע םע דדומתהל לכויש ידכ ךלש שיבכעל ד

.ףסונ שומישל ותוא ןסחאלו יטנוולר עדימ ץלחל ,טנרטניא רתא לש םינוש םיפד ןיב טוונ

.דומיעה ידקפ תא אוצמל ידכ רתאה תא קודבו Scrapy תפטעמ תא וא ךלש ןפדפדה תא חתפ .

:דומעה תיתחתב דומיעה ירושיק תא ואצמת Books to Scrape רתאב

<li class="next"><a href="catalogue/page-2.html">next</a></li>

.םינוש םירפס יטירפ גיצמו אבה דומעה תא ןעוט רתאהש הארת ,וילע ץחלתשכ .אבה דומעה

:תואצותה יפד לכמ םינותנ דרגלו דומיעב לפטל ידכ ךלש םייקה BookSpider

import scrapy

from books.items import BooksItem

class BookSpider(scrapy.Spider):
    name = "book"
    allowed_domains = ["books.toscrape.com"]
    start_urls = ["https://books.toscrape.com/"]

    def parse(self, response):
        for book in response.css("article.product_pod"):
            item = BooksItem()
            item["url"] = book.css("h3 > a::attr(href)").get()
            item["title"] = book.css("h3 > a::attr(title)").get()
            item["price"] = book.css(".price_color::text").get()
            yield item

        next_page = response.css("li.next > a::attr(href)").get()
        if next_page:
            next_page_url = response.urljoin(next_page)
            yield scrapy.Request(url=next_page_url, callback=self.parse)

.תרזוח תורשקתהכ .parse() תטישב שמתשמו תרשרש התע הזש רתאה תבותכ תא

.הדירגה ךילהתב ךישמהל ךכבו ,תבתכש .parse() תטיש תועצמאב בוש ,םירפ

:םיפדה לכמ םינותנ דרגל ידכ בוש ותוא ליעפהל לוכי התא .דומיע םע דדומתהל תעכ רדגו

(venv) $ scrapy crawl book

Scrapy ןורחאה דומעל עיגיש דע םיאבה םידומעהמ םינותנ ץלחל ךישמתו ,דומיעה ירושיק

.טנרטניא ירתא לש בחר ןווגמ םע דדומתהל םילוכיש רתוי םישימגו םיקזח םידרגמ תונבל

MongoDB -ב םידרוגמה םינותנה תא ןסחא

.ךלש לנימרטב תוארל לוכי התאש (stderr) יטרדנטסה תואיגשה םרזל הלאה םינותנה תא חל

.דיתעה לא הברה דובעל ךישמהלו םינותנ לש תולודג תויומכ םע דדומתהל לגוסמ תויהל רו

.MongoDB ףסואב םידרוגמה םינותנה תא ןסחאל לכות דציכ דמלת ,הז ףיעסב .הצחמל םינבו

ךלש בשחמב MongoDB ףסוא רדגה

.ךלש תכרעמב ותוא ןיקתהל ךילע ,MongoDB -ב שמתשהל ליחתהל לכותש ינפל

:ךלש לנימרטה תועצמאב ךלש הנקתהה תא תמאל לכות ,החלצהב MongoDB תא תנקתהש רחאל

$ mongod --version
db version v7.0.12
Build Info: {
    "version": "7.0.12",
    "gitVersion": "b6513ce0781db6818e24619e8a461eae90bc94fc",
    "modules": [],
    "allocator": "system",
    "environment": {
        "distarch": "aarch64",
        "target_arch": "aarch64"
    }
}

.בוש תוסנלו הנקתהה תא בוש קודבל ךרטצת ,תאז םוקמב האיגש תעדוה ךל ןתונ ךלש ףוסמה

.םינותנ ןוסחאל ותוא ןיכהל ידכ הרדגה תומישמ המכ עצבל ךרטצתש ןכתיי ,MongoDB -ב ש

:המָגוּדלְ .תונוכנה תואשרהה תא הל שיש אדוולו וז היירפס רוציל ךילע היהיש ןכתיי .

$ sudo mkdir -p /data/db
$ sudo chown -R `id -u` /data/db

.27017 לדחמה תרירב תאיציל ותוא דגאיו MongoDB תרש תא ליעפת וז הלוע

:םינותנ דסמ תולועפ עצבל ךל רשפאיו MongoDB תרשל ךתוא רבחי הז .ךלש לנימרטב

$ mongosh
Current Mongosh Log ID: 66868598a3dbed30a11bb1a2
Connecting to:          mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.2.10
Using MongoDB:          7.0.12
Using Mongosh:          2.2.10

For mongosh info see: https://docs.mongodb.com/mongodb-shell/

test>

:books ףסואלו books_db םינותנה דסמל ארקת התא .שדח ףס

test> use books_db
switched to db books_db
books_db> db.createCollection("books")
{ ok: 1 }
books_db> show collections
books
books_db>

.ךלש שדחה םירפס ףסואל םכרד תא ואצמי םידרוגמה םינותנה לכש ךכ הז תא

Scrapy-מ MongoDB לש םינותנ דסמל רבחתה

:PyPI-מ pymongo תא ןיקתהל ךרטצת ,תישאר .ךלש Scrapy-ה טקיורפ ךותמ

(venv) $ python -m pip install pymongo

.ךלש Scrapy-ה טקיורפל ךלש MongoDB עפומ לע עדימ ףיסוהל ןכומ התא ,הנקתהה תמלשה ר

.וב שמתשהל לוכי התא תופסונ תורדגה וליא יבגל תורעה הברה םג ליכמ אוה .םיוסמ עדימ

:ץבוקה תיתחתב MongoDB לש רוביחה יטרפ תא ףסוהו settings.py תא חתפ

# ...

MONGO_URI = "mongodb://localhost:27017"
MONGO_DATABASE = "books_db"

.םאתהב עדימה תא םיאתהל ךרטצת ,חראתמ MongoDB עפומל רבחתמ התא םא .ךלש ימוקמה בשח

Scrapy רוניצ תועצמאב םינותנה תא דבע

.ETL לש הדובע תמירז לש הניעטה ךילהת תא דהדהמ ,ךלש שדחה MongoDB ףסואב

:טנרטניאהמ םתוא דרג ךלש שיבכעהש רחאל םיטירפ דוביעל תוטיש רפסמ הרידגמש Python ל

  • .open_spider() חתפנ שיבכעה רשאכ ארקנ.
  • .close_spider() רגסנ שיבכעה רשאכ ארקנ.
  • .process_item() גירח תולעהל וא טירפ ריזחהל וילע .טירפ רוניצ ביכר
  • .from_crawler() מ רוניצ רצוי-קרוס רוניצל תונימזל תוי

.םידרוגמ םינותנ תומיא וא HTML ינותנ יוקינ ןוגכ ,תורחא תורטמל םג םהב שמתשהל לוכ

:ףסואל םידרוגמה םיטירפה תא סינכיו MongoDB -ל רבחתי הז רוניצ .books/pipel

import pymongo
from itemadapter import ItemAdapter

class MongoPipeline:
    COLLECTION_NAME = "books"

    def __init__(self, mongo_uri, mongo_db):
        self.mongo_uri = mongo_uri
        self.mongo_db = mongo_db

    @classmethod
    def from_crawler(cls, crawler):
        return cls(
            mongo_uri=crawler.settings.get("MONGO_URI"),
            mongo_db=crawler.settings.get("MONGO_DATABASE"),
        )

    def open_spider(self, spider):
        self.client = pymongo.MongoClient(self.mongo_uri)
        self.db = self.client[self.mongo_db]

    def close_spider(self, spider):
        self.client.close()

    def process_item(self, item, spider):
        self.db[self.COLLECTION_NAME].insert_one(ItemAdapter(item).asdict())
        return item

:השוע קלח לכש המ הנה .boilerplate דוק אוה ובור ,תאז םע .דוק לש לודג שוג ומכ תו

  • itemadapter ב תולתכ הנקתוה הליבחה .הדיחא הרוצב םהב לפטל ידכ םינוש

  • COLLECTION_NAME ףסוא לש םשה תא ןייצמ MongoDB ןכל םדוק תרדגהש ףסוא

  • .__init__() ה םע רוניצה תא לחתאמ-URI לש MongoDB מ ותוא איבמ התאש

  • .from_crawler() לש הבילה יביכר לכל השיג ךל הקינעמה הקלחמ תטיש איה

  • .open_spider() ל רוביח חתופ-MongoDB ליחתמ שיבכעה רשאכ.

  • .close_spider() רוביח תא רגוס MongoDB םייסמ שיבכעה רשאכ.

  • .process_item() ףסואל דרוגמ טירפ לכ ףיסומ MongoDB. רוניצ לש הבילה

.האבה הלעפהב וב שמתשת תרגסמהש ךכ ךלש טקיורפה לש רשקהב ותוא ליעפהל ךרטצת ןיידע

:ךלש שדחה רוניצה טקייבוא לש םאתומה םשה םוקימ תא ףיסוהל ןכמ רחאלו ,Python תרעה

ITEM_PIPELINES = {
    "books.pipelines.MongoPipeline": 300,
}

.רתוי ההובג תופידע םשוריפ רתוי םיכומנ םירפסמ .תורוניצה תא ליעפמ Scrapy ובש רדס

.ךלש טנרטניאה דוריג תומישמב הקלח הרוצב הניעט תולועפ ןהו היצמרופס

םילופכ םיכרע תפסוהמ ענמיה

:1000 יכמסמ ליכמ אוהש הארת ,וגנומ תפטעמב תינושארה הצירה רחאל ךלש

books_db> db.books.countDocuments()
1000

.ךלש םינותנה דסמב םינותנ לופכשל ליבומש המ ,שדח ההזמ ול הצקיו שדח ךמסמכ דרגש טי

.ךמסמ לכ תוהזל ידכ שמתשהל לוכי MongoDB ובש ךלש םינותנה רובע ידוחיי ההזמ הדש ןי

:דדובה ףדה לש רתאה תבותכ לש hash-מ קיפתש שדח ידוחיי id הדש ךמס לע

import hashlib
import pymongo
from itemadapter import ItemAdapter
from scrapy.exceptions import DropItem

class MongoPipeline:
    COLLECTION_NAME = "books"

    def __init__(self, mongo_uri, mongo_db):
        self.mongo_uri = mongo_uri
        self.mongo_db = mongo_db

    @classmethod
    def from_crawler(cls, crawler):
        return cls(
            mongo_uri=crawler.settings.get("MONGO_URI"),
            mongo_db=crawler.settings.get("MONGO_DATABASE"),
        )

    def open_spider(self, spider):
        self.client = pymongo.MongoClient(self.mongo_uri)
        self.db = self.client[self.mongo_db]

    def close_spider(self, spider):
        self.client.close()

    def process_item(self, item, spider):
        item_id = self.compute_item_id(item)
        if self.db[self.COLLECTION_NAME].find_one({"_id": item_id}):
            raise DropItem(f"Duplicate item found: {item}")
        else:
            item["_id"] = item_id
            self.db[self.COLLECTION_NAME].insert_one(ItemAdapter(item).asdict())
            return item

    def compute_item_id(self, item):
        url = item["url"]
        return hashlib.sha256(url.encode("utf-8")).hexdigest()

:.compute_item_id() השדחה רזעה תטיש תא תפסוהו .process_item

  • 4-ו 1 תורוש יטרדנטסה היירפסה לודומ רובע דחא ,םישדח אוביי ינש

  • 28 הרוש ל תארוק-.compute_item_id() ל בוביגה טלפה

  • 30-ו 29 תורוש ףסואב תותליאש תועצבמ MongoDB ותוא םע טירפ םייק

  • 34 דע 31 תורוש יאנתה תא תוביכרמ else, תא ףיסומ ה

.הלאכ םינוב םתייה םא םירחא תורוניצ ידי לע ףסונ דוביע רשפאמ הז .טירפה תא הריזחמ

:ךלש טירפה תרדגהל ותוא ףסוהו books/items.py תא חתפ .BooksIt

import scrapy

class BooksItem(scrapy.Item):
    _id = scrapy.Field()
    url = scrapy.Field()
    title = scrapy.Field()
    price = scrapy.Field()

:ךלש דוקב םינוש תומוקמ ינשמ BooksItem לכ סלכאמ התא תעכו ,ךלש שיבכ

  1. .BooksItem.price.url, .titl
  2. ..url-מ ובושיח רחאל ,._id רובע ךרעה תא ףיסומ ךלש טיר

.ךלש טנרטניאה דרגמ תיינב תעב ךל עיצמ Scrapy לש םינבומה םיכילהתב שומישהש תושימג

.םכלש ףסואל URL תבותכ התואמ םיימעפ םתדריגש רפס םוש ףיסוי אל Python-ש ושוריפ יד

.הזה טירפה תא לטבי יחכונה םושייה יזא - URL תבותכ התוא לע הרימש ךות - ונתשי הלא

:Python דוקל וזה הלועפה תא םגרתמ pymongo

# ...

    def process_item(self, item, spider):
        item_id = self.compute_item_id(item)
        item_dict = ItemAdapter(item).asdict()

        self.db[self.COLLECTION_NAME].update_one(
            filter={"_id": item_id},
            update={"$set": item_dict},
            upsert=True
        )

        return item

# ...

.MongoDB םע היצקארטניא תעב תורישי ךמסמה לש _id תא רצויו טירפה םאת

:םיירקיע םיטנמוגרא ינש ריבעהל ךירצ התא זא ,pymongo םע .upda

  1. ךלש ףסואב ךמסמה תא אוצמל ידכ ןנסמה
  2. ןוכדעה תלועפ

.ךלש ףסואב םיכמסמה תא רוציל ידכ קר וב שמתשמו ןנסמ טנמוגרא -המ הזה ךרעה תא חקול

:דעוימה טקפאה תא לבקי הז דוקש ינפל ,ןמזה תמתוח יססובמ םיהזמה תא ליכמ ןיידעש ,ך

books_db> db.books.drop()
true
books_db> db.books.countDocuments()
0

.ףלא לע דימת ראשיהל ךירצ רפסמה .ךלש ףסואב ךל שי םיכמסמ המכ קודבל זאו ,םימעפ המ

.םישדח םינותנב םימייק םיכרע ןכדעלו םילופכ םיטירפ לטבל לכות דציכ רתוי בוט גשומ

ךלש Scrapy Web Scraper-ה תא קודבו םיגאב רותיא

.ןנכותמכ םילעופ םהש חיטבהלו ךלש םישיבכעב םיגאב תופנל ךל ורזעיש המצוע יבר םילכ

.ןפוד תאצוי הניא תשר תדירגו ,הנכות חותיפ ךילהת לכב עירכמ קלח ןה תוקידב .הפוצמכ

.הפוצמכ דבוע ךלש שיבכעהש רשאל ידכ תישיא תומאתומ תודיחי תוקידב המכ בותכת םג התא

רגול םע ןמוי עדימ

.logger-ל השיג שי רבכ םישיבכע םיטקייבואל יכ ,ותוא אבייל ךירצ אל וליפא התא .תיט

:שדח ףדל טוונמ ךלש שיבכעה יתמ ירחא בוקעל ידכ םושיר ףסוהו ךלש book.py

# ...

    def parse(self, response):
        for book in response.css("article.product_pod"):
            item = BooksItem()
            item["url"] = book.css("h3 > a::attr(href)").get()
            item["title"] = book.css("h3 > a::attr(title)").get()
            item["price"] = book.css(".price_color::text").get()
            yield item

        next_page = response.css("li.next > a::attr(href)").get()
        if next_page:
            next_page_url = response.urljoin(next_page)
            self.logger.info(
                f"Navigating to next page with URL {next_page_url}."
            )
            yield scrapy.Request(url=next_page_url, callback=self.parse)

# ...

.INFO םושיר תמר םע שדח ףדל טוונמ שיבכעה רשאכ עדימ דעתמו ךלש BookSpider

.ךלש ףוסמל תוספדומה רתוי ההובג הרמוחו INFO לש תועדוה קר תוארל ידכ וז המרל רובע

:settings.py-ב םיעובק ךרד תורישי ךלש שיבכעל תורבחתהה תא רידגהל לו

# ...

LOG_LEVEL = "INFO"

.הלעמו INFO לש הרמוח תגרדב םינמוי קר אלא ,םיגאב יופינ לע עדימ םוש הארת אל .תרח

.רחא ףדל טווינ Scrapy-ש עדימה תא קר לבקת ,קיר ףסוא סלכאמ התאש ןמזב שיבכעה תא ל

:MongoPipeline.process_item()-ב רומשל תטלחה תויוליפכ תעינמ לש הקי

  • .שדח ףדל טוונמ Scrapy רשאכ ןמויה תועדוה תא קר הארת זא ,pymongo לש .updat

  • .DropItem גירח ספות אוה רשאכ הרהזא תיטמוטוא בתוכ Scrapy .הרהזא ינ

:ןמויה ץבוקל קר תורהזא בותכי Python-ש ךכ LOG_LEVEL-ה תא בוש םיאתה

# ...

LOG_LEVEL = "WARNING"
LOG_FILE = "book_scraper.log"

.ךלש Scrapy טקיורפב ןמויה ץבוק םוקימ תאו םושירה תמר תא תישיא תמאתה ,וללה תורדג

:DropItem-ב שמתשמש דוקה םע דבוע התאש החנהב - ודרוהש םיטירפה לכ לע

2024-08-28 13:11:32 [scrapy.core.scraper] WARNING: Dropped: Duplicate item found: {'price': '£51.77',
 'title': 'A Light in the Attic',
 'url': 'catalogue/a-light-in-the-attic_1000/index.html'}
{'price': '£51.77',
 'title': 'A Light in the Attic',
 'url': 'catalogue/a-light-in-the-attic_1000/index.html'}
...

!שבתשה אל רבד םושש תעדל בוט .קיר ןמוי ץבוק תוארל רומא התא זא ,תוילע םע דבוע הת

.הצירב לשכיהל םייתסי אוהש הרקמל השע ךלש שיבכעהש המ לע רוזחל ךל רשפאל ידכ ,ץבוק

errback םע תואיגשב לפט

Scrapy רטמרפל הטיש ריבעת םא .האיגש לש תרזוח תורשקתה תייצקנופ תועצמאב ןחב תואיג

:תואיגשב לפטל ידכ ךלש שיבכעל השדח הטיש ףסוהו book.py תא חתפ

import scrapy

from books.items import BooksItem

class BookSpider(scrapy.Spider):
    # ...

    def log_error(self, failure):
        self.logger.error(repr(failure))

.שיבכעה עוציב תא רוצעל ילבמ תויעב ןוחבאב ךל רוזעל לוכי הז .ERROR לש הרמוח תמרב

:ךלש .log_error() תטיש תועצמאב תואיגשב לפטי Scrapy-ש חיטבהל לוכי

# ...

def parse(self, response):
  # ...

  if next_page:
      next_page_url = response.urljoin(next_page)
      self.logger.info(
          f"Navigating to next page with URL {next_page_url}."
      )
      yield scrapy.Request(
          url=next_page_url,
          callback=self.parse,
          errback=self.log_error,
      )

.ומשריי האיגש םיריזחמה םירפסה תונחב םיפסונ םיפדל תושקב לכש חיטבמ התא ,sc

:.start_urls-ב לע קר ךמתסהל םוקמב .start_requests()-

# ...

class BookSpider(scrapy.Spider):
    name = "book"
    allowed_domains = ["books.toscrape.com"]
    start_urls = ["https://books.toscrape.com/"]

    def start_requests(self):
        for url in self.start_urls:
            yield scrapy.Request(
                url, callback=self.parse, errback=self.log_error
            )

    def parse(self, response):
        # ...

.ךלש טנרטניאה דוריג ישיבכעב האיגשה יאנת תא תוליעיב רפשלו רותפל לכות ,err

.ןנכותמכ לעופ םכלש דרגמהש חיטבהל ידכ תוקידב בותכל ולכות דציכ לכתסת תעכ ,העיצמ

שיבכע יזוח המכ לע םותח

Scrapy הנוכמה הנוכת העיצמםיזוח, ל המודב .ךלש שיבכעה לש תוזורח

:תוטישה לש היופצה תוגהנתהה תא םירידגמ םה .ךלש שיבכעה תוטיש לש תזורחמב ביצהל לו

  • @url ש רתאה תבותכ תא ןייצמ-Scrapy איבהל ךירצ.
  • @returns ריזחהל ךירצ שיבכעהש תושקב וא םיטירפ לש
  • @scrapes ליכהל םיכירצ םיטירפהש תודשה תא טרפמ.

:ךלש .parse() תטישל הזוח ףסוהו ךלש book.py ץבוקה תא

# ...

    def parse(self, response):
        """
        @url https://books.toscrape.com
        @returns items 20 20
        @returns request 1 50
        @scrapes url title price
        """
        for book in response.css("article.product_pod"):
            # ...

:.parse() לש קודה תזורחמל םיזוח העברא תפסוה

  1. @url https://books.toscrape.com ל רמוא-Scrapy תורחאה תוקידבהמ תחא
  2. @returns items 20 20 םומיסקמה אוה ינשהו ,םייופצה םיילמינימה םיטיר
  3. @returns request 1 50 ש ושוריפ-.parse() תרדגהש דומיע
  4. @scrapes url title price תודשה תא ליכהל ךירצ רזחוהש טירפ לכש ןייצ

.םדקומ בלשב ךלש דרגמה םע תויעב תוהזל ךל רוזעל תולוכיש .parse() רו

:ךלש לנימרטב check הדוקפב שמתשהל לוכי התא ,הזוחה תוקידב תא עצבל י

(venv) $ scrapy check book
...
----------------------------------------------------------------------
Ran 3 contracts in 1.399s

OK

.שבתשה המ תנייצמה האיגש תעדוה איצות תרגסמה ,תלשכנ תונעטהמ תחא םא .קודה תזורחמב

.םיזוח השולש הלהינ Scrapy-ש בתכנ העדוהבש הביסה וזו ,טלפב הקידב יאנתכ הז תא טרפ

.תוקידבה תא עצבלו ןגראל ידכ unittest-ב םישמתשמ םיזוח ,עונמה הסכמל

:ןוגכ ,תונורתי המכ םיללוכ שיבכע יזוח ,רוציקב

  • ריהמ תומיא: הכלהכ תולעופ ךלש שיבכעה תוטישש אדוול הצור התא רשא

  • דועית: המ ןמז רחאל דוקב שדחמ רוקיב תעב וא תווצה ירבח רובע ליע

  • תויטמוטוא תוקידב: ךלש דוקה סיסבב םייוניש עצבמ התאשכ הכלהכ דוב

.םינוש םיאנתב הפוצמכ םילעופ םהש אדוולו ,ךלש טנרטניאה ידרגמ לש הקוזחתהו תונימאה

תטרופמ הקידבל הדיחי תוקידב בותכ

.םידדוב םיביכר קודבל ידכ הדיחי תוקידב בותכל בוט ןויער תויהל לוכי הז ,טוריפ רתי

.הפוצמכ תוגהנתמ ךלש שיבכעה תוטישש חיטבהל ידכ םיגלגלמ תושקבו תובוגתב ךורכ הז .S

:םיצבק ינש רוצ ,הייקית התוא ךותב .tests/ תייקית רוצ ,הנוילעה המרב

  • __init__.py תליבחכ היקיתה תא לחתאמ Python.
  • test_book.py ךלש דרגמה רובע הדיחיה תוקידב תא םייקי.

.תיפיצפס תפסות םע הז לע תונבל זאו ,ךלש שיבכעה יזוח םיסכמ רבכש המ תא שדחמ לוקשל

.הזה רסחה תא אלמל ידכ הדיחי ןחבמ בותכל בוט ןויער תויהל לוכי הז .ץלחמ אוהש םיטנ

:דומיעל רתאה תבותכ רובע השדח השקב תרצויו םירפסה לכ תא תרזחאמ ,HTML-המ םינוכנה

import unittest

class BookSpiderTest(unittest.TestCase):

    def test_parse_scrapes_all_items(self):
        """Test if the spider scrapes books and pagination links."""
        pass

    def test_parse_scrapes_correct_book_information(self):
        """Test if the spider scrapes the correct information for each book."""
        pass

    def test_parse_creates_pagination_request(self):
        """Test if the spider creates a pagination request correctly."""
        pass

if __name__ == "__main__":
    unittest.main()

.יוארכ דקפתל ידכ הכירצ הקידב לכש השורדה הרדגהה תא תרצויש .setUp()

:.setUp() תטישל רובעל בוט דמעומ הז ,ןחבמ לכ רובע וז הרדגהל קקדזתש

import unittest
from scrapy.http import HtmlResponse
from books.spiders.book import BookSpider

class BookSpiderTest(unittest.TestCase):
    def setUp(self):
        self.spider = BookSpider()
        self.example_html = """
            Insert the example HTML here
        """
        self.response = HtmlResponse(
            url="https://books.toscrape.com",
            body=self.example_html,
            encoding="utf-8"
        )

# ...

.ךלש דוקה סיסב תא עירכהל ילבמ ,יתימאה ףדה לש HTML-ל רשפאה לככ בורק היהי המגודל

:books/tests/sample.html-ב הדרוהל םינתינה םירמוחהמ הזה ךירדמה שמת

.self.example_html-ל ותוא תוצקהל ידכ תולופכ-תושלושמה תואכרמה ןיב

:לשכיהל ךלש ןושארה ןחבמל םורגל לוכי התא ,םוקמב ךלש הרדגהה םע

# ...

class BookSpiderTest(unittest.TestCase):
    # ...

    def test_parse_scrapes_all_items(self):
        """Test if the spider scrapes all books and pagination links."""
        # There should be two book items and one pagination request
        book_items = []
        pagination_requests = []

        self.assertEqual(len(book_items), 2)
        self.assertEqual(len(pagination_requests), 1)

:unittest הדוקפה תא לעפה ,םש רבכ ךניא םא ,ךלש הנוילעה המרב

(venv) $ python -m unittest
.F.
======================================================================
FAIL: test_parse_scrapes_all_items (tests.test_book.BookSpiderTest.test_parse_scrapes_all_items)
Test if the spider scrapes all items including books and pagination links.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/path/to/books/tests/test_book.py", line 169, in test_parse_scrapes_all_items
    self.assertEqual(len(book_items), 2)
AssertionError: 0 != 2

----------------------------------------------------------------------
Ran 3 tests in 0.011s

FAILED (failures=1)

:רובעי ןחבמהש ידכ םירסחה םיקלחה תא ופיסוהו דוקל הרזח וצפק .הלש רזחהה ךרעב לפטמ

# ...

from scrapy.http import HtmlResponse, Request
from books.items import BooksItem

class BookSpiderTest(unittest.TestCase):
    # ...

    def test_parse_scrapes_all_items(self):
        """Test if the spider scrapes all books and pagination links."""
        # Collect the items produced by the generator in a list
        # so that it's possible to iterate over it more than once.
        results = list(self.spider.parse(self.response))

        # There should be two book items and one pagination request
        book_items = [item for item in results if isinstance(item, BooksItem)]
        pagination_requests = [
            item for item in results if isinstance(item, Request)
        ]

        self.assertEqual(len(book_items), 2)
        self.assertEqual(len(pagination_requests), 1)

.books.items-מ הז תא אביימ התא זא ,BooksItem-ב רפסה

.ךלש תונעטה לומ קדוב התאש המ הז זא ,דומיע לש תחא רתא תבותכו רפס יטירפ ינש ליכמ

:רובעל תורומא תוקידבה תשולש לכו ,תרחא םעפב unittest תא ץירהל לכות

(venv) $ python -m unittest
...
----------------------------------------------------------------------
Ran 3 tests in 0.011s

:םושייל המגוד אוצמל לכות ,הטמל לפקתמה קלחב .המוד השיגב תורחאה הקידבה תוטיש יתש

:ךלש test_book.py ץבוקב ותוא קיבדהלו הטמל דוקה תא קיתעהל לוכי התא

import unittest

from scrapy.http import HtmlResponse, Request

from books.items import BooksItem
from books.spiders.book import BookSpider


class BookSpiderTest(unittest.TestCase):
    def setUp(self):
        self.spider = BookSpider()
        self.example_html = """
            Insert the example HTML here
        """
        self.response = HtmlResponse(
            url="https://books.toscrape.com",
            body=self.example_html,
            encoding="utf-8",
        )

    def test_parse_scrapes_all_items(self):
        """Test if the spider scrapes all books and pagination links."""
        # Collect the items produced by the generator in a list
        # so that it's possible to iterate over it more than once.
        results = list(self.spider.parse(self.response))

        # There should be two book items and one pagination request
        book_items = [
            item for item in results if isinstance(item, BooksItem)
        ]
        pagination_requests = [
            item for item in results if isinstance(item, Request)
        ]

        self.assertEqual(len(book_items), 2)
        self.assertEqual(len(pagination_requests), 1)

    def test_parse_scrapes_correct_book_information(self):
        """Test if the spider scrapes the correct information for each book."""
        results_generator = self.spider.parse(self.response)

        # Book 1
        book_1 = next(results_generator)
        self.assertEqual(
            book_1["url"], "catalogue/a-light-in-the-attic_1000/index.html"
        )
        self.assertEqual(book_1["title"], "A Light in the Attic")
        self.assertEqual(book_1["price"], "£51.77")

        # Book 2
        book_2 = next(results_generator)
        self.assertEqual(
            book_2["url"], "catalogue/tipping-the-velvet_999/index.html"
        )
        self.assertEqual(book_2["title"], "Tipping the Velvet")
        self.assertEqual(book_2["price"], "£53.74")

    def test_parse_creates_pagination_request(self):
        """Test if the spider creates a pagination request correctly."""
        results = list(self.spider.parse(self.response))
        next_page_request = results[-1]
        self.assertIsInstance(next_page_request, Request)
        self.assertEqual(
            next_page_request.url,
            "https://books.toscrape.com/catalogue/page-2.html",
        )


if __name__ == "__main__":
    unittest.main()

:הדרוהל םיבאשמב books/tests/sample.html-ב אוצמל לכותש המגודל HTML

.חותיפה ךילהתב םדקומ בלשב תויעב ןקתלו תוהזל תרזועו ,תונוכנ רותיאל םיקדבנ

םיצופנ טנרטניא דוריג ירגתא םע דדומתה

.ןימאו קזח טנרטניא דרגמ תיינבל ינויח וללה םילושכמה םע דדומתהל םינכומ תויהל ,הד

.ולש תבחרנה תיגולוקאה תכרעמהו Scrapy תועצמאב םהילע רבגתהל םיישעמ תונורתפ המכ ר

.רתוי םירגתאמ םירתאמ םג ךרע ירקי םינותנ ץלחל םילגוסמה םידימע םידרגמ תונבל רתוי

ולשכנש תושקב בוש הסנ

.לשכיהל ךלש שיבכעל ומרגי אל תוינמז תויעבש אדוול תרזוע ךלש טקיורפב רזוח ןויסינ

Scrapy תואיגש לש םימיוסמ םיגוסב ולקתנש תושקב לש רזוח ןויסינל תינבומ הכימת תקפס

:ךלש טקיורפה רובע םיאתהל הצרת ילואש שולש שי ,תונימזה הרוצתה תויורשפא ןיבמ .ךלש

  • RETRY_ENABLED: לדחמ תרירבכ לעפומ הז .רזוח ןויסינ לש עצמאה תנכות ת
  • RETRY_TIMES: םיימעפ הלשכנש השקב בוש הסנמ תרגסמה ,לדחמ תרירבכ .הלש
  • RETRY_HTTP_CODES: תבוגת ידוק תא רידגמ HTTP רזוח ןויסינ ליעפהל םיר

:settings.py ץבוקב הלאה םיכרעה תא תונשל לוכי התא זא ,לדחמה תרירבל

# ...

RETRY_TIMES = 3
RETRY_HTTP_CODES = [500, 429]

.דרגמה יטקיורפ בור רובע בוט ןויער ללכ ךרדב איה תמשיימ Scrapy-ש לדחמה תרירב תור

.תופלוח תויעב לש העפשהה תא תיחפהלו רתוי ןימא םינותנ ץוליח גישהל לוכי התא ,הז ל

ימניד ןכות םע דדומתה

:םהב ןיינועמ התאש םינותנל השיג לבקל ןיידע ידכ טוקנל לוכי התאש תושיג המכ שי .ימ

  • תושקב לפכש: תואירק תועצמאב ךל םישורדה םינותנה תא באוש ךלש ןפד

  • ב שמתשה-Splash לש שארמ דוביעל JavaScript: Splash דבעל ךל רשפא

  • יטמוטואל ןפדפד ךופה: ומכ םילכ Selenium ו-Playwright עוציב ללו

.הדובעה תא עצבל ךל ורזעיש תוליעומ תויצרגטניא ךל תקפסמ Scrapy ,ךלש טנרטניאה דור

הדירג דגנ םינונגנמ להנ

.הנתשמ ץמאמ תדימב וללה םיעצמאהמ קלח ףוקעל לוכי התא .םהלש םיבאשמב ןגוה שומיש חי

Scrapy ץבוקב תורישי רתויב תוצופנה תושיגהמ המכ תישיא םיאתהל ךל רשפאמ sett

:יתימא ןפדפד תוקחל רוזעל הלוכי ךלש טקיורפה תורדגהב תישיא םאתומ שמתשמ ןכוס תרדג

# ...

USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3"

:המיסחל יוכיסה תא תיחפהלו תושקב ץיפהל רוזעל לוכיש המ ,יסקורפו םישמתשמ ינכוס בב

# ...

DOWNLOADER_MIDDLEWARES = {
    "scrapy.downloadermiddlewares.useragent.UserAgentMiddleware": None,
    "scrapy_user_agents.middlewares.RandomUserAgentMiddleware": 400,
}

# ...

:טוב-יטנא יעצמא תלעפהמ ענמיהל רוזעל םג לוכיש המ ,תושקב ןיב םיבוכיע סינכהל לוכי

# ...

DOWNLOAD_DELAY = 2

:לדחמ תרירבכ תלעפומה ,ךכל הרדגה םג שי Scrapy-ל .טנרטניא יקרוס רובע רתאה לש תוא

# ...

ROBOTSTXT_OBEY = True

# ...

.היצקארטניא םתיא םייקמ התאש םירתאה תא םידבכמו םיליעי ,םיקזח ךלש םידרגמהש חיטבה

הנָקָסְמַ

!הפי הדובע .ETL-ה ךילהת רחא בקועש םלש טנרטניא דוריג טקיורפל MongoDB-בו Scrapy-

.הדירג-יטנא ינונגנמ תפיקעו ימניד ןכות םע תודדומתה ,םירזוח תונויסינ לוהינ ןוגכ

דציכ תדמל ,הז ךירדמב:

  • טקיורפ רדגהו רדגה
  • Scrapy םע תילנויצקנופ טנרטניא תדרגמ ונב
  • םינותנ ץלח תועצמאב םירתאמ םיררוב
  • ןסחא לש םינותנ דסמב םידרוגמ םינותנ MongoDB
  • םיגאב יופינו קודב לש טנרטניאה דרגמ תא Scrapy ךלש

!דבכמ ראשיהו דרגל ךישמת .בטיה ךתוא ותרשי הזה ךירדמהמ תרבצש םילכהו עדיה ,טנרטני


כל הזכויות שמורות. © Python-3.com • 2024