Java爬虫(3)——拼接url抓取“加载更多”内容

来源:互联网 发布:playmemories mac版 编辑:程序博客网 时间:2024/05/18 21:50


 

上期我们说到phantomjs可模拟点击按钮行为,通过点击完所有”加载更多”按钮来抓所有内容。比如这个网页http://e.vnexpress.net/news/news


我们要抓取红线所标注的超链接,将url入库,点击“view more stories”会出现更多列表,然而有些网页是,点到所有隐藏内容都出现后,那个“view more stories”按钮还是存在,给判断模拟点击行为何时终止造成困难。或许聪明的朋友会说:“有什么困难的?模拟一次点击行为,抓取一次网页,从下至上获取列表项的url,当url与数据库中已经抓取的url重复时,停止获取。当从下至上获取的第一个url就与数据库中的url重复时,说明已经获取整张网页的所有内容,可停止模拟点击行为……“。这的确是个办法,但存在着大量判断和对网页的重复抓取,我们有个更优雅的解决方式,何乐而不为呢??(另外真要模拟的话selenium比phantomjs更稳定的…)

想必大家通过标题就已经知道接下来我要说的所谓的更优雅的方式是什么了吧……没错!拼接url。

打开控制台的network模块,


点击“view morestories”按钮,出现以下网络请求,注意这个type为xhr的网络请求,这正是向后台请求更多列表项的。观察请求头,


请求的参数有两个,于是尝试拼接url如下

http://e.vnexpress.net/news/news?cate_id=1003894&page=4

得到了13个列表项,但是点击加载更多按钮,新增的却是15个,也只是少了两个列表项,不怎么影响整体抓的效果,就采用此方式来抓了,拼到什么时候为止呢??当page参数大于实际最大页数时,有的网页是不出现“view more stories”按钮,有的仍然出现按钮,但显示的都是最大页数那一页的内容。根据不同情况来判断是否停止抓取。

下面来贴代码:(大部分基础代码已在前文解释过,就不赘述了)

package edu.nju.opsource.vnexpress.linktype;

 

import java.io.InputStream;

import java.util.Date;

import java.util.LinkedList;

 

import org.jsoup.Jsoup;

import org.jsoup.nodes.Document;

import org.jsoup.nodes.Element;

import org.jsoup.select.Elements;

 

import com.onezetta.downloader.EasyHttpDownloader;

 

importedu.nju.opensource.common.beans.ELinkState;

importedu.nju.opensource.common.beans.Link;

importedu.nju.opensource.common.beans.LinkType;

importedu.nju.opensource.common.beans.Site;

importedu.nju.opsource.vnexpress.utils.IdXmlUtil;

 

public class LinkType_NewsList extendsLinkType {

      privateDocument doc = null;

      privateSite site = null;

      privateLinkedList<Link> newItems = null;

      privateLink nextPage = null;

 

      publicLinkType_NewsList() {

            super();

            //TODO Auto-generated constructor stub

      }

 

      publicLinkType_NewsList(String linkTypeName) {

            super.setLinkTypeName(linkTypeName);

      }

 

      publicLinkType_NewsList(Site site) {

 

            super.setLinkTypeName("vnexpress.newslist");

            this.site= site;

      }

 

      publicvoid get(String url) {

 

            super.get(url);

            Stringcontent = new EasyHttpDownloader(url).run();

 

            if(content != null) {

 

                  this.doc= Jsoup.parse(content, this.site.getUrl().getUrl());

 

                  System.out.println("... has Crawled.");

            }else {

                  setState(ELinkState.CRAWLFAILED);

                  System.out.println("... crawled failed.");

            }

      }

 

      //把新闻列表条目的链接插入表

// 在总项目中被调用的核心函数handle()   

@Override

      publicboolean handle(Link parentlink) throws Exception {

 

            if(getState() == ELinkState.CRAWLFAILED)

                  returnfalse;

 

            Elementsnews = this.doc.select("div.list_news_folder.col_720h4.title_news_site");

 

            this.newItems= new LinkedList();

 

            booleanflag = false;

            for(Element newItem : news) {

                  Elementstmp = newItem.select("a");

                  if((tmp != null) && (tmp.size() != 0)) {

                       Linklink = new Link(tmp.first().attr("abs:href"), new LinkType_News(),ELinkState.UNCRAWL, parentlink,

                                   this.site).setLinkDate(new java.sql.Date(new Date().getTime()));

                       //System.out.println(tmp.first().attr("abs:href"));

                       intrst = link.insert();

                       if(rst == -1)

                             flag= true;// link exist

                  }

            }

            if(flag) {

 

                  setState(ELinkState.CRAWLED);

                  returnfalse;

            }

 

            ElementsnextPageE = this.doc.select("a#vnexpress_folder_load_more");

          String url = getNextPageUrl();

            if((nextPageE != null) && (nextPageE.size() != 0)) {

 

                 

                  System.out.println(url);

                  this.nextPage= new Link(url, new LinkType_NewsList(this.site), ELinkState.UNCRAWL,parentlink, this.site).setLinkDate( new java.sql.Date(new Date().getTime()));

                  this.nextPage.insert();

            }

            else{

                  IdXmlUtil.setIdByName("news",2 + "");

            }

            setState(ELinkState.CRAWLED);

            returntrue;

 

      }

 

      publicstatic String getNextPageUrl() {

            intid = IdXmlUtil.getIdByName("news");

// IdXmlUtil用来存储当前已抓取的pageid其实这个工具完全没必要,因为数据库的//url有此参数啊。。。当时脑抽没想到,搞麻烦了。。。

            IdXmlUtil.setIdByName("news",(id + 1) + "");

//此文章的精髓

            Stringurl = "http://e.vnexpress.net/news/news?cate_id=1003894&page=" +id;

 

            returnurl;

      }

     

 

      @Override

      publicString getLinkTextData() {

            //TODO Auto-generated method stub

            returnnull;

      }

 

      @Override

      publicInputStream getLinkBinaryData() {

            //TODO Auto-generated method stub

            returnnull;

      }

 

      @Override

      publicString getLinkUniqeID(String paramString) {

            //TODO Auto-generated method stub

            returnnull;

      }

 

      @Override

      publicDate getLinkDate() {

            //TODO Auto-generated method stub

            returnnull;

      }

 

      publicSite getSite() {

            returnthis.site;

      }

 

      @Override

      publicvoid setSite(Site site) {

            //TODO Auto-generated method stub

            this.site= site;

      }

 

      publicLinkedList<Link> getNewItems() {

            returnthis.newItems;

      }

 

      publicvoid setNewItems(LinkedList<Link> newItems) {

            this.newItems= newItems;

      }

 

      publicLink getNextPage() {

            returnthis.nextPage;

      }

 

      publicvoid setNextPage(Link nextPage) {

            this.nextPage= nextPage;

      }

 

      @Override

      publicString toString() {

            return"LinkType_newsList [doc=" + doc + ", site=" + site +", newItems=" + newItems + ", nextPage="

                       +nextPage + "]";

      }

}

本以为爬虫系列写到这儿就完结了的,其实还有个问题,就是我们在浏览器上试url来查看效果,然而有的网站以这种方式尝试看不到任何内容,这是因为浏览器输入网址是以get请求,有些网站的后台内容不接受get请求。这样的话,我们该怎样查看拼接url的效果呢???

期待下期吧  >0<

 

0 0