代码也可以从我的开源项目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(); } }