#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. Это работает отлично! Спасибо! Мне просто нужно было внести некоторые коррективы в текущие файлы, и это работает безупречно.