代碼也可以從我的開源項目HtmlExtractor中獲取。
當我們在進行數據抓取的時候,如果目標網站是以Js的方式動態生成數據且以滾動頁面的方式進行分頁,那么我們該如何抓取呢?
如類似今日頭條這樣的網站:http://toutiao.com/
我們可以使用Selenium來搞定這件事情。Selenium的設計目的雖然是用於Web應用程序的自動化測試,但是卻非常適合用來做數據抓取,可以非常簡單地繞過網站的反爬蟲限制,因為Selenium直接運行在瀏覽器中,就像真正的用戶在操作一樣。
使用Selenium,我們不但可以抓取Js動態生成數據的網頁,而且可以抓取以滾動頁面方式分頁的網頁。
首先,我們使用maven引入Selenium依賴:
< dependency > < groupId >org.seleniumhq.selenium</ groupId > < artifactId >selenium-java</ artifactId > < version >2.47.1</ version > </ dependency >
接下來就可以寫代碼抓取了:
import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; import java.util.List; import java.util.Random; /** * 如何抓取Js動態生成數據且以滾動頁面方式分頁的網頁 * 以抓取今日頭條為例說明:http://toutiao.com/ * Created by ysc on 10/13/15. */ public class Toutiao { public static void main(String[] args) throws Exception{ //等待數據加載的時間 //為了防止服務器封鎖,這里的時間要模擬人的行為,隨機且不能太短 long waitLoadBaseTime = 3000 ; int waitLoadRandomTime = 3000 ; Random random = new Random(System.currentTimeMillis()); //火狐瀏覽器 WebDriver driver = new FirefoxDriver(); //要抓取的網頁 driver.get( "http://toutiao.com/" ); //等待頁面動態加載完畢 Thread.sleep(waitLoadBaseTime+random.nextInt(waitLoadRandomTime)); //要加載多少頁數據 int pages= 5 ; for ( int i= 0 ; i<pages; i++) { //滾動加載下一頁 driver.findElement(By.className( "loadmore" )).click(); //等待頁面動態加載完畢 Thread.sleep(waitLoadBaseTime+random.nextInt(waitLoadRandomTime)); } //輸出內容 //找到標題元素 List<WebElement> elements = driver.findElements(By.className( "title" )); int j= 1 ; for ( int i= 0 ;i<elements.size();i++) { try { WebElement element = elements.get(i).findElement(By.tagName( "a" )); //輸出標題 System.out.println((j++) + "、" + element.getText() + " " + element.getAttribute( "href" )); } catch (Exception e){ System.out.println( "ignore " +elements.get(i).getText()+ " because " +e.getMessage()); } } //關閉瀏覽器 driver.close(); } }