2016-11-02 5 views
3

У меня есть сайты в БД я хочу ползать последовательно, то есть:Ползающие домены серийно Scrapy

  1. Добавить домен в список разрешенных доменов (должно быть пустым).
  2. Добавить этот домен для запроса (добавление http:// к нему отлично работает).
  3. Сканировать запрос, касающийся разрешенных доменов.
  4. Переход к следующему домену, добавьте его только в список разрешенных доменов. Там будет единственный, так что крест-крест не произойдет. Примечание: criss-cross question не помог мне, но, может быть, мне что-то не хватает ...
  5. Сканировать этот запрос.
  6. Завершить все области, которые у меня есть - серийно.

То, что я достиг до сих пор, - это сканирование доменов, это отличная работа, она полна запросов. Единственная проблема, с которой я столкнулся, заключается в том, что allowed_domains, кажется, не обновляется, он просматривает всевозможные сайты.

Я поставил DEPTH_LIMIT=1 поэтому он не будет бесконечным ползать, и я также добавил DF ползать и не BF ползать:

DEPTH_LIMIT= 1 
SCHEDULER_DISK_QUEUE = 'scrapy.squeues.PickleFifoDiskQueue' 
SCHEDULER_MEMORY_QUEUE = 'scrapy.squeues.FifoMemoryQueue' 

Вот код моего паука (только начало, так как вы не» т действительно заботится о моей обработке пункта ...):

from __future__ import with_statement 
import scrapy 
from scrapy.spiders import CrawlSpider, Rule 
from scrapy.linkextractors import LinkExtractor 
from scrapy.http.request import Request 
from company.items import CompanyItem, UrlItem 
from urlparse import urlparse 
import MySQLdb 
import json 


class RecipeSpider(CrawlSpider): 
    name = "company" 

    allowed_domains = [] 
    start_urls = [] 
    rules = (Rule(LinkExtractor(allow=(), deny=(), tags=('a', 'link', 'li' 'area')), callback='extract_raw_recipe', follow=True),) 

    def start_requests(self): 
     # print "before sources" 
     sources = self.get_allowed_domains() 
     dummy_tuple = (long(len(sources) + 1), u'dummy', None, None, None, None, None, 0L, long(len(sources) + 1),) 
     final_sources = sources + (dummy_tuple,) 

     for source in final_sources: 
      self.allowed_domains = [str(source[1])] 
      url_string = str("http://" + source[1]) 
      self.start_urls = [url_string] 
      self.update_running_source(source) 
      yield Request(url_string, self.extract_raw_recipe) 
    ### start_requests() 

    def extract_raw_recipe(self, response): 
     pass 

код extract_raw_recipe не имеет никаких запросов или разбор следующий URL-адрес, он просто работает, поэтому нет необходимости редактировать его. Но если мне нужно что-то добавить, скажите мне, потому что, возможно, это недостающее звено. Текущий код добавляет словарь к элементу, а затем помещает этот элемент в БД.

Итак, в заключение: что мне нужно добавить, чтобы он мог фильтровать домены каждый раз, когда он просканирует запрос?

Пожалуйста, дайте мне знать, если есть необходимость предоставить больше кода.

ответ

3

Мое предложение было бы принять совершенно иной подход. Создайте очередь в своей базе данных доменов, которые необходимо обходить (на основе любых критериев, которые вы хотите), затем выберите один домен для обхода и инициализации паука соответствующими доменами в списке allowed_domains. Как только паук будет завершен, заново запустите другой обход для следующего домена. Повторяйте до тех пор, пока все домены в очереди не будут завершены.

Это даст вам значительно больший контроль над всем процессом (например, перескакивание неудачных обходов, отмена проблемных обходов и переходов без потери прогресса, сканирование нескольких доменов одновременно без «перекрестных помех» и т. Д.) Если вы планируете расширять это, это также позволит вам делать такие вещи, как пользовательские настройки (например, USER_AGENT, DUPEFILTER, DOWNLOAD_DELAY) или настраиваемые правила для каждого домена, значительно расширяя удобство использования паука.


Если это не вариант, вы можете восстановить свой allowed_domains список. Есть некоторые проблемы с этим, но сначала некоторые предпосылки о фильтрации оффсайта Scrapy.

OffSiteMiddleware несет ответственность за составление списков разрешенных доменов на основании allowed_domains.Для этого использовалось регулярное выражение, которое скомпилировано только один раз при запуске паука (с использованием сигнала spider_opened). Обновление переменной allowed_domains не повлияет на паука, если вы также не вынудите OffSideMiddleWare повторно скомпилировать его регулярное выражение.

Следующий метод (помещается в ваш паук) должны быть доступны для замены вашего allowed_domains с новым списком:

from scrapy.spidermiddlewares.offsite import OffsiteMiddleware 

def change_allowed_domains(self, allowed_domains): 
    self.allowed_domains = allowed_domains 

    for middleware in self.crawler.engine.scraper.spidermw.middlewares: 
     if isinstance(middleware, OffsiteMiddleware): 
      middleware.spider_opened(self) 

Это сбросит domains_seenset() что в OffsiteMiddleware использования, так что имейте это в виду, если вы используете его для чего-либо еще.

Таким образом, принимая во-вторых, чтобы поглотить все, что проблема начинает поверхность: текущий способ изменения allowed_domains как вы в очереди каждый домен в start_requests() не будет работать, так как Spider класса только отслеживает один allowed_domains регулярное выражение (которое вообще не ассоциируется с объектами запроса/ответа). Если вы ставите двадцать запросов в разные домены (каждый раз изменяя список allowed_domains), прежде чем сканер начнет сканирование, он будет использовать последнее скомпилированное регулярное выражение (то есть allowed_domains для домена с последней очередью).

Чтобы преодолеть это, вам нужно либо выполнить сканирование всех запросов для одного домена, написать свой собственный OffsiteMiddleware с помощью слотов, и обработать его всю фильтрацию. Или вы можете создать разницу, чтобы добавить следующий домен в список только после завершения всех запросов в очереди, и все слоты в загрузчике пустые (вероятно, путем проверки self.crawler.engine.slot.inprogress и `self.crawler.engine.slot.scheduler).

Удачи!

+0

Извините, только сейчас у вас было время и ресурсы, чтобы прочитать ваш ответ. Ничего себе, мне много о чем подумать и подумать, спасибо вам большое, попробуем и обновим. –

+0

Пробовал это, он отлично поработал, чтобы отделить запросы и позволить обработать каждый участок в отдельном потоке. –

+0

хотел бы увидеть обновление вашего кода – wprins

 Смежные вопросы

  • Нет связанных вопросов^_^