2016-08-19 56 views
1

我使用python Selenium和Scrapy來抓取網站。如何製作硒腳本更快?

,但我的劇本是如此緩慢,

Crawled 1 pages (at 1 pages/min) 

我使用CSS選擇器,而不是爲XPATH優化的時間。 我改變midllewares

'tutorial.middlewares.MyCustomDownloaderMiddleware': 543, 

是硒是太慢了,或者我應該在設置改變些什麼?

我的代碼:

def start_requests(self): 
    yield Request(self.start_urls, callback=self.parse) 
def parse(self, response): 
    display = Display(visible=0, size=(800, 600)) 
    display.start() 
    driver = webdriver.Firefox() 
    driver.get("http://www.example.com") 
    inputElement = driver.find_element_by_name("OneLineCustomerAddress") 
    inputElement.send_keys("75018") 
    inputElement.submit() 
    catNums = driver.find_elements_by_css_selector("html body div#page div#main.content div#sContener div#menuV div#mvNav nav div.mvNav.bcU div.mvNavLk form.jsExpSCCategories ul.mvSrcLk li") 
    #INIT 
    driver.find_element_by_css_selector(".mvSrcLk>li:nth-child(1)>label.mvNavSel.mvNavLvl1").click() 
    for catNumber in xrange(1,len(catNums)+1): 
     print "\n IN catnumber \n" 
     driver.find_element_by_css_selector("ul#catMenu.mvSrcLk> li:nth-child(%s)> label.mvNavLvl1" % catNumber).click() 
     time.sleep(5) 
     self.parse_articles(driver) 
     pages = driver.find_elements_by_xpath('//*[@class="pg"]/ul/li[last()]/a') 

     if(pages): 
      page = driver.find_element_by_xpath('//*[@class="pg"]/ul/li[last()]/a') 

      checkText = (page.text).strip() 
      if(len(checkText) > 0): 
       pageNums = int(page.text) 
       pageNums = pageNums - 1 
       for pageNumbers in range (pageNums): 
        WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "waitingOverlay"))) 
        driver.find_element_by_css_selector('.jsNxtPage.pgNext').click() 
        self.parse_articles(driver) 
        time.sleep(5) 

def parse_articles(self,driver) : 
    test = driver.find_elements_by_css_selector('html body div#page div#main.content div#sContener div#sContent div#lpContent.jsTab ul#lpBloc li div.prdtBloc p.prdtBDesc strong.prdtBCat') 

def between(self, value, a, b): 
    pos_a = value.find(a) 
    if pos_a == -1: return "" 
    pos_b = value.rfind(b) 
    if pos_b == -1: return "" 
    adjusted_pos_a = pos_a + len(a) 
    if adjusted_pos_a >= pos_b: return "" 
    return value[adjusted_pos_a:pos_b] 
+1

你能提供你的代碼嗎?沒有代碼很難幫助優化。我會首先考慮的是,是否在每次請求時啓動硒引擎,因爲啓動可能是此處最耗時的部分。 – Granitosaurus

+0

@Granitosaurus我用我的代碼更新了我的問題 – parik

回答

5

所以,你的代碼有幾個在這裏的缺陷。

  1. 當scrapy選擇器更快更高效時,您可以使用selenium解析頁面內容。
  2. 您爲每個響應啓動一個webdriver。

這可以通過使用scrapy的Downloader middlewares非常雄辯! 您想要創建一個自定義下載器中間件,它可以使用硒而不是scrapy下載器來下載請求。

例如我用這個:

# middlewares.py 
class SeleniumDownloader(object): 
    def create_driver(self): 
     """only start the driver if middleware is ever called""" 
     if not getattr(self, 'driver', None): 
      self.driver = webdriver.Chrome() 

    def process_request(self, request, spider): 
     # this is called for every request, but we don't want to render 
     # every request in selenium, so use meta key for those we do want. 
     if not request.meta.get('selenium', False): 
      return request 
     self.create_driver() 
     self.driver.get(request.url) 
     return HtmlResponse(request.url, body=self.driver.page_source, encoding='utf-8') 

激活你的中間件:

# settings.py 
DOWNLOADER_MIDDLEWARES = { 
    'myproject.middleware.SeleniumDownloader': 13, 
} 

然後在你的蜘蛛,你可以指定哪些網址通過硒司機將中繼參數下載。

# you can start with selenium 
def start_requests(self): 
    for url in self.start_urls: 
     yield scrapy.Request(url, meta={'selenium': True}) 

def parse(self, response): 
    # this response is rendered by selenium! 
    # also can use no selenium for another response if you wish 
    url = response.xpath("//a/@href") 
    yield scrapy.Request(url) 

這種方法的優點是,你的驅動程序正在啓動只有一次,只用來下載網頁的源文件,其餘的留給適當的異步scrapy工具。
缺點是你不能點擊按鈕等等,因爲你沒有暴露給驅動程序。大多數情況下,您可以通過網絡檢查員對按鈕的功能進行逆向工程,並且您絕不需要單擊驅動程序本身。

+0

感謝您的回答,但這不是我的情況的問題,因爲我們一次調用parse juste,所以我剛剛開始我的webdrive,我試着不解析頁面內容,它也很慢 – parik

+0

你也可以嘗試將'parse'中的代碼移動到'start_requests',因爲你正在使用scrapy下載器下載請求,而不是使用它,然後打開webdirver並下載相同的請求並解析它。另外你也不應該關注scrapy統計數據,我相信'爬行1頁(1頁/分鐘)'是這個數據能顯示的最小值,所以這並不意味着蜘蛛花了1分鐘解析,就好像你在10公里每小時跑100米並不意味着你花了一個小時才能做到這一點。 – Granitosaurus