java爬虫抓取动态网页(【学习】morestories模拟点击按钮行为比phantomjs更稳定)
优采云 发布时间: 2021-09-19 16:14java爬虫抓取动态网页(【学习】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