代碼也可以從我的開源項目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();
}
}
