Scrapy для печати результатов в режиме реального времени, а не ожидания завершения обхода

#python #scrapy

#python #scrapy

Вопрос:

Возможно ли, чтобы scrapy печатал результаты в режиме реального времени? Я планирую сканировать большие сайты и боюсь, что если мое vpn-соединение отключится, усилия по сканированию будут просто потрачены впустую, поскольку они не будут печатать никаких результатов.

В настоящее время я использую VPN с вращающимися агентами пользователей, и я знаю, что идеально использовать вращающиеся прокси вместо VPN, но это будет для будущего обновления скрипта.

 import scrapy
import re
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor

results = open('results.csv','w')

class TestSpider(CrawlSpider):
    name = "test"
    with open("domains.txt", "r") as d:
        allowed_domains = [url.strip() for url in d.readlines()]

    with open("urls.txt", "r") as f:
        start_urls = [url.strip() for url in f.readlines()]
        f.close()

    rules = (Rule(LinkExtractor(allow=('/'), deny=('9','10')), follow=True, callback='parse_item'),)

    def parse_item(self, response):
        for pattern in ['Albert Einstein', 'Bob Marley']:
            result = re.findall(pattern, response.text) 
            print(response.url,">",pattern,'>',len(result), file = results)
 

Заранее большое спасибо.

Обновления

Скрипт от harada работает отлично без каких-либо изменений, кроме файла сохранения. Все, что мне нужно было сделать, это внести некоторые изменения в текущие файлы, как показано ниже, чтобы все заработало.

элементы, определяемые пауком

 import scrapy
import re
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
from ..items import TestItem

class TestSpider(CrawlSpider):
    name = "test"
    with open("domains.txt", "r") as d:
        allowed_domains = [url.strip() for url in d.readlines()]

    with open("urls.txt", "r") as f:
        start_urls = [url.strip() for url in f.readlines()]
        f.close()

    rules = (Rule(LinkExtractor(allow=('/'), deny=('9','10')), follow=True, callback='parse_item'),)

    def parse_item(self, response):

        items = TestItem()

        for pattern in ['Albert Einstein', 'Bob Marley']:
            result = re.findall(pattern, response.text) 
            url = response.url
            count = len(result)

            items['url'] = url
            items['pattern'] = pattern
            items['count'] = count

            yield(items)
 

items.py — добавлены элементы в виде полей

 import scrapy

    class TestItem(scrapy.Item):
        url = scrapy.Field()
        pattern = scrapy.Field()
        count = scrapy.Field()
 

settings.py — раскомментированный ITEM_PIPELINES

 ITEM_PIPELINES = {
   'test.pipelines.TestPipeline': 300,
}
 

Ответ №1:

Вы можете добавить в свой конвейер скрипт, который может сохранять имеющиеся у вас на тот момент данные в файл. Добавьте счетчик в конвейер в качестве переменной, и когда конвейер достигает определенного порога (скажем, каждые 1000 элементов), он должен записывать в файл. Код будет выглядеть примерно так. Я постарался сделать его как можно более общим.

 class MyPipeline:
    def __init__(self):
        # variable that keeps track of the total number of items yielded
        self.total_count = 0
        self.data = []

    def process_item(self, item, spider):
        self.data.append(item)
        self.total_count  = 1
        if self.total_count % 1000 == 0:
            # write to your file of choice....
            # I'm not sure how your data is stored throughout the crawling process
            # If it's a variable of the pipeline like self.data,
            # then just write that to the file
            with open("test.txt", "w") as myfile:
                myfile.write(f'{self.data}')

        return item
 

Комментарии:

1. Спасибо! Я только что запустил Scrapy / Python неделю назад, поэтому я просто пытаюсь понять, как и что добавить в процессы.

2. @AJ2 Нет проблем, я отредактировал свой ответ для большей ясности моего примера. Теоретически вы можете (и настоятельно рекомендуется) использовать экспорт ленты вместо этого. Смотрите здесь для получения дополнительной информации: docs.scrapy.org/en/stable/topics/feed-exports.html

3. Это работает отлично! Спасибо! Мне просто нужно было внести некоторые коррективы в текущие файлы, и это работает безупречно.