2012-05-24 3 views
2

로드 된 페이지의 모든 링크를 크롤링하고 모든 요청 및 응답 헤더를 응답 본문과 함께 일부 파일에 XML 또는 txt로 기록하는 크롤러를 작성하려고합니다.캐시에 요소가 없습니다. Selenium Ruby 웹 드라이버에서 찾은 페이지가 변경되었을 수 있습니다.

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 메서드를 사용하여 다른 입력 값을 채울 수 있으며이 오류가 발생하지 않습니다. 오류 : 캐시에서 요소를 찾을 수 없습니다 - 페이지가 변경되었을 수 있습니다. 쳐다 보았다.

열려있는 각 창에서 입력 태그를 감지하고 구분하여 대부분의 웹 사이트 페이지에 나타나는 공통 입력 태그에서 값이 반복적으로 채워지지 않게하는 방법은 무엇입니까? 내 코드는 다음입니다 : 내가 셀레늄 Webdriver를 사용하거나 루비의 net/httphttp.set_debug_output를 사용하여 응답 본문 모든 requeat 및 응답 헤더를 얻을 수있는 방법

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) 

나를 안내?

답변

1

Selenium은 "웹 크롤러"를 빌드하는 데 사용할 수있는 최상의 옵션 중 하나가 아닙니다. 그것은 예기치 않은 시나리오를 가로막을 때 때때로 너무 희박 할 수 있습니다. Selenium WebDriver는 예상치와 사용자 상호 작용을 자동화하고 테스트하기위한 훌륭한 도구입니다. 대신 오래된 구식 곱슬 곱슬 함이 웹 크롤링에 더 좋은 옵션 일 수 있습니다. 또한, 나는 당신이 웹 크롤 링을 도울 수있는 몇 가지 루비 보석이 있다는 것을 확신합니다. 단지 Google 검색뿐입니다!

하지만 셀레늄 WebDriver를 사용한다면 실제 질문에 대답하려면

난 당신이 당신이 변수 배열과 상호 작용하는 요소의 HTML을 추가 할 수있는 필터링 알고리즘을 해결 것입니다. 그런 다음 다음 창/탭/링크로 이동하면 변수 배열을 검사하여 일치하는 HTML 값을 찾으면 요소를 건너 뜁니다.

불행히도 SWD는 API로 요청 헤더와 응답을 가져 오는 것을 지원하지 않습니다. 일반적인 해결 방법은 타사 프록시를 사용하여 요청을 차단하는 것입니다.

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

이제 난 당신의 코드 몇 가지 문제를 해결하고 싶습니다.

링크를 반복하기 전에 @default_current_window = @driver.window_handle을 추가하시기 바랍니다. @driver.switch_to.window(@default_current_window)으로 전화하면 스크립트 끝 부분에서 항상 올바른 창으로 돌아갈 수 있습니다.

@links iterator에서 표시 할 수있는 모든 가능한 창을 반복하는 대신 @driver.switch_to.window(@driver.window_handles.last)을 사용하십시오. 그러면 가장 최근에 표시된 새 창으로 전환됩니다 (링크 당 한 번만 클릭하면됩니다!).

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 당신이 반복 하나의 배열 변수에 찾아 원하는 모든 요소를 ​​추가하는 방법을 참고 :

이 같은 일을하여 입력 및 양식 코드를 건조 할 수 있습니다 . 그런 다음, 뭔가 나쁜 일이 생기면, 단일 구조가 필요합니다. (필자는 거기에서 자동으로 종료하고 싶지 않으므로 화면에 메시지를 인쇄하려고합니다).

코드를 익히고 외부 보석을 사용하는 방법을 배우면 빠르게하고 싶은 것을 많이 얻을 수 있습니다.