抓取网站文章
0
本段代码主要功能根据文章列表分页抓取文章,主要使用了jsoup
,里面所有的选择器都可jQuery里面的选择器类似。
代码如下:
package com.acgist.spider;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
/**
* 文章抓取蜘蛛
*/
public class Spider {
private String domain; // 文章链接地址
private String domainName; // 文章网站名称
private String firstPage; // 第一页
private String pageSelector; // 文章分页列表选择器
private String listSelector; // 文章列表选择器
private String titleSelector; // 文章标题选择器
private String contentSelector; // 文章内容选择器
private int totalArticleNum = 0; // 当前抓取文章数量
private int maxArticleNum = 1000; // 最大抓取文章数量
private boolean status = true; // 状态
private static final long sleepTime = 10 * 1000; // 休眠时间
private static final int timeoutMillis = 10 * 1000; // 超时时间
private static final String URL_REGEX = "http[s]?://([a-zA-Z0-9]+\\.)?([a-zA-Z0-9]+\\.[a-zA-Z0-9]+)(/|/.+)?"; // URL正则表达式
public static void main(String[] args) {
Spider spider = new Spider("http://www.acgist.com", "ACGIST动漫",
"http://www.acgist.com/article/type?id=3001",
".page a", ".article li a", ".title", ".articlemsg");
spider.findArticles();
}
public Spider() {
}
/**
* 初始化爬虫
* @param domain 主域名
* @param domainName 网站名称
* @param firstPage 第一页
* @param pageSelector 分页选择器
* @param listSelector 文章列表选择器
* @param titleSelector 文章标题选择器
* @param contentSelector 文章内容选择器
*/
public Spider(String domain, String domainName, String firstPage, String pageSelector, String listSelector, String titleSelector, String contentSelector) {
this.domain = domain;
this.domainName = domainName;
this.firstPage = firstPage;
this.listSelector = listSelector;
this.pageSelector = pageSelector;
this.titleSelector = titleSelector;
this.contentSelector = contentSelector;
}
/**
* 查找文章
* @return 文章
*/
public void findArticles() {
if(StringUtils.isEmpty(this.domain) || StringUtils.isEmpty(this.firstPage))
throw new RuntimeException("主域名和第一页地址不能为空");
if(!this.domain.matches(URL_REGEX) || !this.firstPage.matches(URL_REGEX))
throw new RuntimeException("主域名和第一页地址不正确:domain:" + this.domain + "----firstPage:" + this.firstPage);
Document document;
try {
document = Jsoup.parse(new URL(firstPage), timeoutMillis);
pagePageHandle(document);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 获取分页信息
* @param document 第一页的文档
* @throws IOException 异常
* @throws MalformedURLException 异常
* @throws InterruptedException 异常
*/
private void pagePageHandle(Document document) throws MalformedURLException, IOException, InterruptedException {
List<String> pageUrls = new ArrayList<String>();
pageUrls.add(firstPage); // 第一页
Elements elements = document.select(pageSelector);
for (Element element : elements) {
String href = null;
if(element.hasAttr("href"))
href = element.attr("href");
if(StringUtils.isNotEmpty(href)) {
if(!href.matches(URL_REGEX))
href = domain + href;
if(href.matches(URL_REGEX) && !pageUrls.contains(href))
pageUrls.add(href);
}
}
for (String pageUrl : pageUrls) {
if(!status)
return;
articleListHandle(pageUrl);
Thread.sleep(sleepTime);
}
}
/**
* 处理文章列表
* @param pageUrl 当前文章url
* @throws MalformedURLException 异常
* @throws IOException 异常
*/
private void articleListHandle(String pageUrl) throws MalformedURLException, IOException {
List<String> articleUrls = new ArrayList<String>();
Document document = Jsoup.parse(new URL(pageUrl), timeoutMillis);
Elements elements = document.select(listSelector);
for (Element element : elements) {
String href = null;
if(element.hasAttr("href"))
href = element.attr("href");
if(StringUtils.isNotEmpty(href)) {
if(!href.matches(URL_REGEX))
href = domain + href;
if(href.matches(URL_REGEX) && !articleUrls.contains(href))
articleUrls.add(href);
}
}
for (String articleUrl : articleUrls) {
if(!status)
return;
articleHandle(articleUrl);
}
}
/**
* 处理文章
* @param articleUrl 文章列表
* @throws MalformedURLException 异常
* @throws IOException 异常
*/
private void articleHandle(String articleUrl) throws MalformedURLException, IOException {
Document document = Jsoup.parse(new URL(articleUrl), timeoutMillis);
Elements titles = document.select(titleSelector);
Elements contents = document.select(contentSelector);
if(titles.size() > 0)
System.out.println(titles.get(0).text());
if(contents.size() > 0)
System.out.println(contents.get(0).html());
totalArticleNum++;
if(totalArticleNum > maxArticleNum)
status = false;
System.out.println("\r\n\r\n\r\n\r\n当前抓取文章列表====" + totalArticleNum + "====\r\n\r\n\r\n\r\n");
}
//=================getter setter=================//
public int getMaxArticleNum() {
return maxArticleNum;
}
public void setMaxArticleNum(int maxArticleNum) {
this.maxArticleNum = maxArticleNum;
}
}
代码未大量测试,可能会出现问题。
一些特殊的网站会把其他内容放到文章内容里面,防止一些恶意代码和连接可以使用jsoup过滤。
一些网站的分页连接会使用相对路径。