2

ロードされたページからすべてのリンクをクロールし、すべての要求および応答ヘッダーを応答本文とともに XML または txt などのファイルに記録するクローラーを作成しようとしています。最初に読み込まれたページからすべてのリンクを新しいブラウザー ウィンドウで開いているため、このエラーは発生しません。

Element not found in the cache - perhaps the page has changed since it was looked up

リクエストを作成し、すべてのリンクから応答を受け取り、開いているすべてのウィンドウから入力要素を見つけてボタンを送信する別の方法を知りたいです。開いたウィンドウの右上隅にhttp://www.testfire.netのような一般的なサイト検索ボックスがある場合を除いて、上記をある程度行うことができます。私がやりたいのは、このような一般的なボックスを省略してi.send_keys "value"、webdriver のメソッドを使用して他の入力に値を入力し、このエラーが発生しないようにすることです。エラー: キャッシュに要素が見つかりません - ページが検索されてから変更された可能性があります。 .

Web サイトのほとんどのページに表示される一般的な入力タグで値が繰り返し入力されないように、開いている各ウィンドウから入力タグを検出して区別する方法は何ですか。私のコードは次のとおりです。

require 'rubygems'
require 'selenium-webdriver'
require 'timeout'

class Clicker
def open_new_window(url)
  @driver = Selenium::WebDriver.for :firefox
  @url = @driver.get " http://test.acunetix.com "
  @link = Array.new(@driver.find_elements(:tag_name, "a"))
  @windows = Array.new(@driver.window_handles())
  @link.each do |a|
      a = @driver.execute_script("var d=document,a=d.createElement('a');a.target='_blank';a.href=arguments[0];a.innerHTML='.';d.body.appendChild(a);return a", a)
      a.click
    end
    i = @driver.window_handles
    i[0..i.length].each do |handle|
        @driver.switch_to().window(handle)
        puts @driver.current_url()
        inputs = Array.new(@driver.find_elements(:tag_name, 'input'))
        forms = Array.new(@driver.find_elements(:tag_name, 'form'))
        inputs.each do |i|
            begin
                i.send_keys "value"
                puts i.class
                i.submit
                rescue Timeout::Error => exc
                    puts "ERROR: #{exc.message}"
                rescue Errno::ETIMEDOUT => exc
                    puts "ERROR: #{exc.message}"
                rescue Exception => exc
                    puts "ERROR: #{exc.message}"
            end
        end 
        forms.each do |j|
            begin
                j.send_keys "value"
                j.submit
                rescue Timeout::Error => exc
                    puts "ERROR: #{exc.message}"
                rescue Errno::ETIMEDOUT => exc
                    puts "ERROR: #{exc.message}"
                rescue Exception => exc
                    puts "ERROR: #{exc.message}"
            end
        end

    end
#Switch back to the original window
    @driver.switch_to().window(i[0])
end
end
ol = Clicker.new
url = ""
ol.open_new_window(url)

Selenium Webdriverまたはhttp.set_debug_outputrubyを使用して、応答本文を含むすべてのrequeatおよび応答ヘッダーを取得する方法を教えてくださいnet/http

4

1 に答える 1

1

Selenium は、「Web クローラー」を構築するために使用する最適なオプションの 1 つではありません。特に予期しないシナリオに遭遇した場合は特に、不安定すぎる場合があります。Selenium WebDriver は、期待値とユーザー インタラクションを自動化およびテストするための優れたツールです。代わりに、古き良き時代のカールは、おそらく Web クロールに適したオプションです。また、ウェブクロールに役立つルビーの宝石がいくつかあると確信しています。Google で検索してください。

しかし、Selenium WebDriver を使用する場合の実際の質問に答えるには:

対話する要素の HTML を変数配列に追加できるフィルタリング アルゴリズムを作成したいと思います。次に、次のウィンドウ/タブ/リンクに移動すると、変数配列がチェックされ、一致する HTML 値が見つかった場合は要素がスキップされます。

残念ながら、SWD はその API を使用したリクエスト ヘッダーとレスポンスの取得をサポートしていません。一般的な回避策は、サードパーティのプロキシを使用してリクエストをインターセプトすることです。

============

ここで、コードに関するいくつかの問題に対処したいと思います。

リンクを繰り返し処理する前に、 を追加することをお勧めします@default_current_window = @driver.window_handle。これにより、 を呼び出したときに、スクリプトの最後で常に正しいウィンドウに戻ることができます@driver.switch_to.window(@default_current_window)

@links イテレータでは、表示可能なすべてのウィンドウを反復処理する代わりに、 を使用します@driver.switch_to.window(@driver.window_handles.last)。これにより、最後に表示された新しいウィンドウに切り替わります (リンクのクリックごとに 1 回だけ実行する必要があります!)。

次のようにして、入力とフォーム コードを DRY できます。

inputs = []
inputs << @driver.find_elements(:tag_name => "input")
inputs << @driver.find_elements(:tag_name => "form")
inputs.flatten
inputs.each do |i|
  begin
    i.send_keys "value"
    i.submit
  rescue e
    puts "ERROR: #{e.message}"
  end
end

SWD に検索させたいすべての要素を、繰り返し処理する単一の配列変数に追加したことに注目してください。次に、何か悪いことが起こったときに、1 つのレスキューが必要です (そこから自動的に終了したくないと思います。そのため、メッセージを画面に出力したいだけです)。

コードをドライアップして外部の gem を使用することを学ぶと、やろうとしていることの多くをより速いペースで達成するのに役立ちます。

于 2013-04-14T04:11:32.610 に答える