Как работает «download_slot» в рамках scrapy - PullRequest
4 голосов
/ 26 апреля 2019

Я в скрипте создал скрипт, чтобы проанализировать author name различных постов со своей целевой страницы и затем передать его методу parse_page, используя ключевое слово meta, чтобы напечатать post content вместе сauthor name одновременно.

Я использовал download_slot в мета-ключевом слове, которое якобы маскирует выполнение скрипта быстрее.Хотя нет необходимости соблюдать логику, которую я пытался применить здесь, я хотел бы придерживаться ее только для того, чтобы понять, как download_slot работает в любом сценарии и почему.Я много искал, чтобы узнать больше о download_slot , но в итоге я нашел несколько ссылок, таких как this .

Пример использования download_slot(Хотя я не совсем уверен в этом):

from scrapy.crawler import CrawlerProcess
from scrapy import Request
import scrapy

class ConventionSpider(scrapy.Spider):
    name = 'stackoverflow'
    start_urls = ['https://stackoverflow.com/questions/tagged/web-scraping']

    def parse(self,response):
        for link in response.css('.summary'):
            name = link.css('.user-details a::text').extract_first()
            url = link.css('.question-hyperlink::attr(href)').extract_first()
            nurl = response.urljoin(url)
            yield Request(nurl,callback=self.parse_page,meta={'item':name,"download_slot":name})

    def parse_page(self,response):
        elem = response.meta.get("item")
        post = ' '.join([item for item in response.css("#question .post-text p::text").extract()])
        yield {'Name':elem,'Main_Content':post}

if __name__ == "__main__":
    process = CrawlerProcess({
        'USER_AGENT': 'Mozilla/5.0',
    })
    process.crawl(ConventionSpider)
    process.start()

Вышеуказанный скрипт работает без нареканий.

Мой вопрос: как download_slot работаетвнутри скрапа?

Ответы [ 2 ]

3 голосов
/ 28 апреля 2019

Давайте начнем с архитектуры Scrapy . Когда вы создаете scrapy.Request, механизм Scrapy передает запрос загрузчику, чтобы получить содержимое. Загрузчик помещает входящие запросы в слоты, которые вы можете представить как независимые очереди запросов. Затем очереди опрашиваются, и каждый отдельный запрос обрабатывается (содержимое загружается).

Теперь вот важная часть. Чтобы определить, в какой слот помещать входящий запрос, загрузчик проверяет request.meta для ключа download_slot. Если он присутствует, он помещает запрос в слот с таким именем (и создает его, если он еще не существует). Если ключ download_slot отсутствует, он помещает запрос в слот для домена (точнее, имени хоста), на который указывает URL запроса.

Это объясняет, почему ваш скрипт работает быстрее. Вы создаете несколько слотов загрузчика, потому что они основаны на имени автора. Если вы этого не сделаете, они будут помещены в один и тот же слот в зависимости от домена (который всегда stackoverflow.com). Таким образом, вы эффективно увеличиваете параллельность загрузки контента.

Это объяснение немного упрощено, но оно должно дать вам представление о том, что происходит. Вы можете проверить код самостоятельно.

1 голос
/ 05 мая 2019

Например, существует некоторый целевой веб-сайт, который позволяет обрабатывать только 1 запрос в 20 секунд, и нам необходимо проанализировать / обработать 3000 веб-страниц данных о продуктах с него.Обычный паук с DOWNLOAD_DELAY, установленным на 20 - приложение завершит работу через ~ 17 часов (3000 pages * 20 seconds задержка загрузки).

Если вы стремитесь увеличить скорость очистки, не будучи заблокированным сайтом, и у вас естьНапример, 20 действительных прокси. Вы можете равномерно распределить URL-адреса запросов по всем прокси, используя мета-ключ proxy и download_slot, и значительно сократить время завершения приложения

from scrapy.crawler import CrawlerProcess
from scrapy import Request
import scrapy

class ProxySpider(scrapy.Spider):
    name = 'proxy'
    start_urls = ['https://example.com/products/1','https://example.com/products/2','....']#list with 3000 products url
    proxies = [',,,'] #list wiht 20 proxies

    def start_requests(self):
        for index, url in start_urls:
            chosen_proxy = proxies(index % len(self.proxies)
            yield Request(url, callback=self.parse,
                          meta = {"proxy":chosen_proxy,"download_slot":chosen_proxy})

    def parse(self,response):
        ....
            yeild item
            #yield Request(deatails_url,
                           callback=self.parse_additional_details,
                           meta= 
                           {"download_slot":response.request.meta["download_slot"],
                            "proxy":response.request.meta["download_slot"]})



if __name__ == "__main__":
    process = CrawlerProcess({
        'USER_AGENT': 'Mozilla/5.0','DOWNLOAD_DELAY':20, "COOKIES_ENABLED":False
    })
    process.crawl(ProxySpider)
    process.start()
.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...