2016-08-19 6 views
1

私はpython SeleniumとScrapyを使ってウェブサイトをクロールします。どのようにセレンのスクリプトを速くするのですか?

が、私のスクリプトは

Crawled 1 pages (at 1 pages/min) 

は、私は時間を最適化するための代わりにXPATHのCSSセレクタを使用し、とても遅いです。 私は

'tutorial.middlewares.MyCustomDownloaderMiddleware': 543, 

midllewaresを変更するには、セレンが遅すぎるか、私は設定で何かを変更する必要がありますか?

私のコード:

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. 治療セレクタがより高速で効率的な場合、セレンを使用してページコンテンツを解析します。
  2. 応答ごとにWebdriverを起動します。

これは、scrapの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, 
} 

は、その後、あなたのクモであなたは、メタ引数を追加することにより、セレンドライバを介してダウンロードするためのURLを指定することができます。

# 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

答えがありがとうございますが、私のケースの問題ではありません。パースジャスティを一度呼び出すので、それは遅すぎる – parik

+0

また、あなたはscreamのダウンローダを使ってリクエストをダウンロードし、それを使用せずにwebdirverを開き、同じリクエストをダウンロードして解析するので、 'parse'のコードを' start_requests'に移動することもできます。また、あなたはすべての時点で治療統計に注意を払うべきではありません。私は '1ページ分(1ページ/分)でクロールされました 'がこの統計が示す最小値だと信じています。あなたが10km/hで100m走行したのと同じように、それを行うのに1時間かかったわけではありません。 – Granitosaurus

関連する問題