java爬虫抓取动态网页(【学习】morestories模拟点击按钮行为比phantomjs更稳定)

优采云 发布时间: 2021-09-19 16:14

  java爬虫抓取动态网页(【学习】morestories模拟点击按钮行为比phantomjs更稳定)

  在上一期中,我们说过phantomjs可以模拟单击按钮的行为,并通过单击所有“加载更多”按钮来获取所有内容。例如,此网页

  我们需要抓取红线标记的超链接,存储URL,然后单击“查看更多故事”以显示更多列表。但是,对于某些网页,“查看更多故事”按钮在所有隐藏内容出现后仍然存在,这使得很难判断模拟点击行为何时终止。也许聪明的朋友会说:“有什么困难?模拟单击行为,抓取网页,并从下到上获取列表项的URL。当URL与数据库中已捕获的URL重复时,停止获取。当从下到上获取的第一个URL与数据库中的URL重复时,这意味着整个网页的所有内容都已获取,模拟点击行为可以停止”。这确实是一种方法,但网页有很多判断和重复爬行。我们有一个更优雅的解决方案。为什么不呢??(此外,如果我们真的想模拟,selenium比phantomjs更稳定…)

  你一定已经知道我接下来想通过标题说什么,所谓的更优雅的方式……没错

  打开控制台的网络模块

  单击“查看更多故事”按钮,将显示以下网络请求。请注意,此类型为XHR的网络请求是从后台请求更多列表项的原因。请观察请求标题

  请求有两个参数,因此请尝试按如下方式拼接URL

  我们得到了13个列表项,但是当我们点击load more按钮时,添加了15个新项,只缺少了两个列表项,这并不影响抓取的整体效果,所以我们使用这种方法抓取它们。当页面参数大于实际最大页数时,一些网页不会出现“查看更多故事”“按钮,某些按钮仍会出现,但会显示最大页数的页面内容。根据不同情况判断是否停止爬网。”

  代码如下:(大部分基本代码已经在前面解释过了,所以我不再重复)

  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;

import edu.nju.opensource.common.beans.ELinkState;

import edu.nju.opensource.common.beans.Link;

import edu.nju.opensource.common.beans.LinkType;

import edu.nju.opensource.common.beans.Site;

import edu.nju.opsource.vnexpress.utils.IdXmlUtil;

public class LinkType_NewsList extends LinkType {

private Document doc = null;

private Site site = null;

private LinkedList newItems = null;

private Link nextPage = null;

public LinkType_NewsList() {

super();

// TODO Auto-generated constructor stub

}

public LinkType_NewsList(String linkTypeName) {

super.setLinkTypeName(linkTypeName);

}

public LinkType_NewsList(Site site) {

super.setLinkTypeName("vnexpress.newslist");

this.site = site;

}

public void get(String url) {

super.get(url);

String content = 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

public boolean handle(Link parentlink) throws Exception {

if (getState() == ELinkState.CRAWLFAILED)

return false;

Elements news = this.doc.select("div.list_news_folder.col_720 h4.title_news_site");

this.newItems = new LinkedList();

boolean flag = false;

for (Element newItem : news) {

Elements tmp = newItem.select("a");

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

Link link = 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"));

int rst = link.insert();

if (rst == -1)

flag = true;// link exist

}

}

if (flag) {

setState(ELinkState.CRAWLED);

return false;

}

Elements nextPageE = 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);

return true;

}

public static String getNextPageUrl() {

int id = IdXmlUtil.getIdByName("news");

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

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

//此文章的精髓

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

return url;

}

@Override

public String getLinkTextData() {

// TODO Auto-generated method stub

return null;

}

@Override

public InputStream getLinkBinaryData() {

// TODO Auto-generated method stub

return null;

}

@Override

public String getLinkUniqeID(String paramString) {

// TODO Auto-generated method stub

return null;

}

@Override

public Date getLinkDate() {

// TODO Auto-generated method stub

return null;

}

public Site getSite() {

return this.site;

}

@Override

public void setSite(Site site) {

// TODO Auto-generated method stub

this.site = site;

}

public LinkedList getNewItems() {

return this.newItems;

}

public void setNewItems(LinkedList newItems) {

this.newItems = newItems;

}

public Link getNextPage() {

return this.nextPage;

}

public void setNextPage(Link nextPage) {

this.nextPage = nextPage;

}

@Override

public String toString() {

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

+ nextPage + "]";

}

}

  我原以为爬虫系列将在这里结束。事实上,另一个问题是我们在浏览器上尝试URL以查看效果。但是,一些网站尝试以这种方式看不到任何内容。这是因为浏览器将URL作为get请求输入,而一些网站后台内容不接受get请求。在这种情况下,我们如何处理ck拼接URL的效果如何

<p>期待下一期>0

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线