0

非常に大量のリンク (約 300) を含む Web ページがあり、これらのリンクに関する情報を収集したいと考えています。

これが私のコードです:

beginning_time = Time.now
#This gets a collection of links from the webpage
tmp = driver.find_elements(:xpath,"//a[string()]")
end_time = Time.now
puts "Execute links:#{(end_time - beginning_time)*1000} milliseconds for #{tmp.length} links"


before_loop = Time.now
#Here I iterate through the links
tmp.each do |link|
    #I am not interested in the links I can't see
    if(link.location.x < windowX and link.location.y < windowY)
        #I then insert the links into a NoSQL database, 
        #but for all purposes you could imagine this as just saving the data in a hash table.
        $elements.insert({
            "text" => link.text,
            "href" => link.attribute("href"),
            "type" => "text",
            "x" => link.location.x,
            "y" => link.location.y,
            "url" => url,
            "accessTime" => accessTime,
            "browserId" => browserId
        })
    end
end
after_loop = Time.now
puts "The loop took #{(after_loop - before_loop)*1000} milliseconds"

現在、リンク コレクションを取得するのに 20 ミリ秒、リンクの情報を取得するのに約 4000 ミリ秒 (または 4 秒) かかります。アクセサーを NoSQL 挿入から分離すると、NoSQL 挿入に 20 ミリ秒しかかからず、ほとんどの時間がアクセサーに費やされていることがわかります (理由はわかりませんが、NoSQL 挿入から分離された後、アクセサーは非常に遅くなりました)。 )、これにより、アクセサーが JavaScript を実行している必要があると結論付けます。

私の質問は、これらのリンクとその情報をより迅速に収集するにはどうすればよいですか?

最初に思いついた解決策は、2 つのドライバーを並行して実行することでしたが、WebDriver はスレッドセーフではないため、WebDriver の新しいインスタンスを作成してページに移動する必要がありました。これにより、ページのソースをダウンロードして別のドライバーにロードできるようにする方法が問題になります。これは Selenium では実行できないため、デスクトップ自動化ツールを使用して Chrome 自体で実行する必要があり、かなりのオーバーヘッドが追加されます。

私が聞いた別の方法は、ChromeDriver の使用をやめ、PhantomJS のみを使用することでしたが、ビジュアル ブラウザーでページを表示する必要があります。

まだ検討していない他の選択肢はありますか?

4

1 に答える 1

1

オブジェクトにアクセスするのではなく、純粋に Javascript を実行するために Webdriver を使用しているようです。

javascript を使用してドロップした場合に試すいくつかのアイデア (Java で失礼しますが、アイデアはわかります)。

 //We have restricted via xpath so will get less links back AND will not haveto check the text within loop
        List<WebElement> linksWithText = driver.findElements(By.xpath("//a[text() and not(text()='')]"));

        for (WebElement link : linksWithText) {

            //Store the location details rather than re-get each time
            Point location = link.getLocation();
            Integer x = location.getX();
            Integer y = location.getY();

            if (x < windowX && y < windowY) {
                ///Insert all info using webdriver commands;
            }
        }

私は通常、リモート グリッドを使用するため、テストではパフォーマンスが重要な懸念事項です。そのため、すべてを取得してループするのではなく、常に CSS セレクターまたは XPath によって制限しようとするのはなぜですか。

于 2013-09-05T08:38:51.363 に答える