使用Selenium來抓取動態加載的頁面

jopen 11年前發布 | 121K 次閱讀 Selenium 網絡爬蟲

有些頁面是通過js以及ajax動態加載的,例如:花瓣網。這時如果我們直接分析原始頁面的html,是得不到有效的信息的。當然,因為無論怎樣動態加載,基礎信息總歸是包含在初始頁面中得,所以我們可以用爬蟲代碼來模擬js代碼,js讀取頁面元素值,我們也讀取頁面元素值;js發送ajax,我們就拼湊參數、發送ajax并解析返回的json。這樣總歸是能做的,但是比較麻煩,有沒有比較省力的方法呢?比較好的方法大概是內嵌一個瀏覽器了。

Selenium是一個模擬瀏覽器,進行自動化測試的工具,它提供一組API可以與真實的瀏覽器內核交互。Selenium是跨語言的,有Java、C#、python等版本,并且支持多種瀏覽器,chrome、firefox以及IE都支持。

在Java項目中使用Selenium,需要做兩件事:

  • 在項目中引入Selenium的Java模塊,以Maven為例:

    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>2.33.0</version>
    </dependency>
    </li>

  • 下載對應的driver,以chrome為例:http://code.google.com/p/chromedriver/downloads/list

    下載后,需要將driver的位置寫到Java的環境變量里,例如我在mac下將其下載到了/Users/yihua/Downloads/chromedriver,則需要在程序里添加以下代碼(當然在JVM參數里寫-Dxxx=xxx也是可以的):

    System.getProperties().setProperty("webdriver.chrome.driver","/Users/yihua/Downloads/chromedriver");

    </li> </ul>

    Selenium的API挺簡單的,核心是WebDriver,下面是動態渲染頁面,并獲取最終html的代碼:

    @Test
        public void testSelenium() {
            System.getProperties().setProperty("webdriver.chrome.driver", "/Users/yihua/Downloads/chromedriver");
            WebDriver webDriver = new ChromeDriver();
            webDriver.get("http://huaban.com/");
            WebElement webElement = webDriver.findElement(By.xpath("/html"));
            System.out.println(webElement.getAttribute("outerHTML"));
            webDriver.close();
        }

    值得注意的是,每次new ChromeDriver(),Selenium都會建立一個Chrome進程,并使用一個隨機端口在Java中與chrome進程進行通信來交互。由此可見有兩個問題:

    • 因此如果直接關閉Java程序,Chrome進程可能是無法關閉的。這里需要顯示的調用webDriver.close()來關閉進程。

      </li>

    • 創建進程的開銷還是比較大的,盡量對webDriver進行復用會比較好。可惜根據官方的文檔,webDriver不是線程安全的,所以我們需要建立一個webDriver池來保存它們。不清楚Selenium是否有這樣的接口,反正我是自己寫了一個WebDriverPool來完成這個任務。

      </li> </ul>

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!