2017-07-22 2 views
0

Je suis en train d'explorer un site qui utilise un chargement paresseux pour les images de produits.Faire défiler automatiquement la page vers le bas dans Splash et Scrapy

Pour cette raison j'ai inclus scrapy-splash afin que le javascript puisse être rendu aussi avec splash je peux fournir un argument wait. Auparavant, j'avais un doute que c'est à cause du moment où le scrapy.Request brut retourne une image de placeholder à la place des originaux.

J'ai également essayé d'attendre l'argument à 29,0 secondes, mais mon robot n'a toujours pas 10 éléments (il devrait contenir 280 éléments en fonction des calculs). J'ai un pipleline d'article qui vérifie si l'image est vide dans l'article ainsi je raise DropItem.

Je ne suis pas sûr, mais j'ai également remarqué que ce n'est pas seulement le problème wait. Il semble que les images soient chargées lorsque je défile vers le bas. Ce que je cherche est un moyen d'automatiser un comportement de défilement vers le bas dans mes demandes.

Voici mon code Araignée

def parse(self, response): 
     categories = response.css('div.navigation-top-links a.uppercase::attr(href)').extract() 
     for category in categories: 
      link = urlparse.urljoin(self.start_urls[0], category) 
      yield SplashRequest(link, callback=self.parse_products_listing, endpoint='render.html', 
             args={'wait': 0.5}) 

Pipeline

class ScrapperPipeline(object): 
    def process_item(self, item, spider): 
     if not item['images']: 
      raise DropItem 

     return item 

Réglages

IMAGES_STORE = '/scrapper/images' 

SPLASH_URL = 'http://172.22.0.2:8050' 

DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter' 


ITEM_PIPELINES = { 
    'scrapper.pipelines.ScrapperPipeline': 300, 
    'scrapy.pipelines.images.ImagesPipeline': 1 
} 


DOWNLOADER_MIDDLEWARES = { 
    'scrapy.downloadermiddleware.useragent.UserAgentMiddleware': None, 
    'scrapy_splash.SplashMiddleware': 725, 
    'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810, 
    # 'custom_middlewares.middleware.ProxyMiddleware': 210, 
} 

Répondre

2

Si vous définissez sur l'utilisation splash cette réponse devrait vous donner quelques conseils: https://stackoverflow.com/a/40366442/7926936

Vous pouvez également utiliser le sélénium dans un DownloaderMiddleware, c'est un exemple que j'ai un scrapper Twitter qui obtenir les 200 premiers tweets d'une page :

from selenium import webdriver 
from scrapy.http import HtmlResponse 
from selenium.common.exceptions import TimeoutException 
from selenium.webdriver.support.ui import WebDriverWait 


class SeleniumMiddleware(object): 

    def __init__(self): 
     self.driver = webdriver.PhantomJS() 

    def process_request(self, request, spider): 
     self.driver.get(request.url) 
     tweets = self.driver.find_elements_by_xpath("//li[@data-item-type='tweet']") 
     while len(tweets) < 200: 
      try: 
       self.driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") 
       WebDriverWait(self.driver, 10).until(
        lambda driver: new_posts(driver, len(tweets))) 
       tweets = self.driver.find_elements_by_xpath("//li[@data-item-type='tweet']") 
      except TimeoutException: 
       break 
     body = self.driver.page_source 
     return HtmlResponse(self.driver.current_url, body=body, encoding='utf-8', request=request) 


def new_posts(driver, min_len): 
    return len(driver.find_elements_by_xpath("//li[@data-item-type='tweet']")) > min_len 

dans la boucle pendant que je suis en attente dans chaque boucle pour les nouveaux tweets jusqu'à ce qu'il ya 200 tweets chargés dans la page et ont 10 secondes d'attente max.