2016-06-09 11 views
0

Ich wurde beauftragt, einen Scraper für eine Property Site zu erstellen, wo die Ergebnisse für die spätere Verarbeitung gespeichert werden. Bei der fraglichen Website handelt es sich um eine landesweite Website, die nicht alle Inhalte in einer einzigen Suche enthält und von Ihnen erwartet, dass Sie eine Region bereitstellen, bevor Sie die Ergebnisse bereitstellen. Um dies zu umgehen, habe ich einen scraper mit scrapy mit mehreren Start-URLs, die mich direkt zu den Regionen, die mich interessiert, erstellt. Die Website ist auch dynamisch bevölkert, so dass ich selen verwenden, um das Javascript auf der Seite und dann folgen die nächste Schaltfläche, bis der Schaber für jede Region abgeschlossen ist. Das funktioniert gut, wenn es eine einzige Start-URL gibt, sobald es mehr als eine URL gibt, auf die ich ein Problem habe. Anfangs funktioniert der Scraper einwandfrei, aber bevor der Webdriver dem 'next' Button bis zum Ende einer Region folgt (z. B. 20 Seiten für eine einzelne Region folgen), bewegt sich der Scraper nur teilweise auf die nächste Region (Start URL) Kratzen des Inhalts der ersten Regionen. Ich habe ausgiebig nach einer Lösung gesucht, aber ich habe noch niemanden mit diesem speziellen Problem gesehen. Irgendwelche Vorschläge wären sehr willkommen. Beispielcode unten:Scraping dynamischer Inhalt mit Selen und Scrapy mit mehreren Start-URLs

from scrapy.spider     import CrawlSpider 
from scrapy.http     import TextResponse 
from scrapy.selector    import HtmlXPathSelector 
from selenium      import webdriver 
from selenium.webdriver.common.by import By 
from selenium.webdriver.support.ui import WebDriverWait 
from selenium.webdriver.support  import expected_conditions as EC 
from selenium.common.exceptions  import TimeoutException 
import time 
from selenium      import webdriver 
from selenium      import selenium 
from selenium_spider.items   import DemoSpiderItem 
from selenium.webdriver.support.ui import WebDriverWait 
from selenium.webdriver.support  import expected_conditions as EC 
from selenium.common.exceptions  import TimeoutException 
import sys 

class DemoSpider(CrawlSpider): 
    name="Demo" 
    allowed_domains = ['example.com'] 
    start_urls= ["http://www.example.co.uk/locationIdentifier=REGION 1234", 
    "http://www.example.co.uk/property-for-sale/locationIdentifier=REGION 5678"] 

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

    def __del__(self): 
     self.selenium.stop() 

    def parse (self, response): 
     self.driver.get(response.url) 


     result = response.xpath('//*[@class="l-searchResults"]') 
     source = 'aTest' 
     while True: 
      try: 
       element = WebDriverWait(self.driver, 10).until(
      EC.element_to_be_clickable((By.CSS_SELECTOR,".pagination-button.pagination-direction.pagination-direction--next")) 
      ) 
       print "Scraping new site --------------->", result 
       print "This is the result----------->", result 
       for properties in result: 
        saleOrRent = properties.xpath('//*[@class = "property-title"]/text()').extract() 
        addresses = properties.xpath('//*[@class="property-address"]/text()').extract() 
        if saleOrRent: 
         saleOrRent = saleOrRent[0] 
         if 'for sale' in saleOrRent: 
          saleOrRent = 'For Sale' 
         elif 'to rent' in saleOrRent: 
          saleOrRent = 'To Rent' 
       for a in addresses: 
        item = DemoSpiderItem() 
        address = a 
        item ["saleOrRent"] = saleOrRent 
        item ["source"] = source 
        item ["address"] = address 
        item ["response"] = response 
        yield item 
       element.click() 
      except TimeoutException: 
        break 
+0

ich genau das gleiche Problem haben! Haben Sie schon eine Lösung gefunden? Ich sehe auch gerade gut aus, wenn ich auf etwas stoße, das ich dich wissen lasse. –

Antwort

0

Ich habe eigentlich nur ein bisschen herumgespielt und es stellt sich als einfacher heraus, als ich dachte. Sie übergeben nur eine erste URL in start_urls, erstellen Sie Ihre separate Liste von manuellen nachfolgenden URLs zu einem Handbuch Request mit der parse-Funktion als Rückruf und verwenden Sie einen Zähler, um den Index für die richtige URL in manual_urls zugreifen, um es an die Anfrage zu übergeben .

Auf diese Weise können Sie selbst entscheiden, wann die nächste URL geladen wird, z. Du bekommst keine Ergebnisse mehr. Nur hier Nachteil ist, dass es sequentielle ist, aber gut ... :-)

Siehe Code:

import scrapy from scrapy.http.request 
import Request from selenium 
import webdriver from scrapy.selector 
import Selector from products_scraper.items import ProductItem 

class ProductsSpider(scrapy.Spider): 
    name = "products_spider" 
    allowed_domains = ['example.com'] 
    start_urls = ['http://www.example.com/first'] 

    global manual_urls 
    manual_urls = [ 
    'http://www.example.com/second', 
    'http://www.example.com/third' 
    ] 

    global manual_url_index 
    manual_url_index = 0 

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

    def parse(self, response): 

     self.driver.get(response.url) 

     hasPostings = True 

     while hasPostings: 
      next = self.driver.find_element_by_xpath('//dd[@class="next-page"]/a') 

      try: 
       next.click() 
       self.driver.set_script_timeout(30) 
       products = self.driver.find_elements_by_css_selector('.products-list article') 

       if(len(products) == 0): 
        if(manual_url_index < len(manual_urls)): 
         yield Request(manual_urls[manual_url_index], 
          callback=self.parse) 
         global manual_url_index 
         manual_url_index += 1 

        hasPostings = False 

       for product in products: 
        item = ProductItem() 
        # store product info here 
        yield item 

      except Exception, e: 
       print str(e) 
       break 



     def spider_closed(self, spider): 
      self.driver.quit()