使用jsoup采集网页实例
以凤凰网为例,采集小说
-
参考书籍:
- jsoup帮助文档 http://www.open-open.com/jsoup/
- jsoup博客: http://www.jb51.net/article/43485.htm
package cn.com.metadata;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import cn.com.metadata.util.WriteToDateBase;
public class BookCollect {
private Map<String, String> cookies = new HashMap<String, String>();
private String imagePath="D:\\image\\";
private Connection conn;
public static void main(String[] args) {
BookCollect bc=new BookCollect();
//出版书库shuku.htm?yc=1&fee=1&o_type=3&f_cate=1
StringBuffer sb1=new StringBuffer();
sb1.append("/shuku.htm?");
sb1.append("yc=1");
sb1.append("&fee=1");
sb1.append("&o_type=3");
sb1.append("&f_cate=1");
//原创书库shuku.htm?yc=0&f_cate=374&s_cate=716&o_type=2&fee=1&tag=
StringBuffer sb2=new StringBuffer();
sb2.append("/shuku.htm?");
sb2.append("yc=0");
sb2.append("&f_cate=374");
sb2.append("&s_cate=716");
sb2.append("&o_type=2");
sb2.append("&fee=1");
sb2.append("&tag=");
//出版书库和原创书库详情页不一样
for(int i=1;i<=2;i++){
if(i==1){
bc.collectionPage(sb1,i);//1:出版书库 2:原创书库
}else{
bc.collectionPage(sb2,i);//1:出版书库 2:原创书库
}
}
}
//分页处理采集信息
public void collectionPage(StringBuffer sb,int type){
String baseUrl="http://v.yc.ifeng.com";
//出版数据库
String pageUrl=baseUrl+sb.toString();
Document document=null;
try {
int pageTotal=1;
int total=0;
document=Jsoup.connect(pageUrl).cookies(cookies).timeout(60 * 1000).ignoreContentType(true).maxBodySize(10 * 1024 * 1024).get();
String pageText=document.select("strong[class=f16 blue]").text();
total=Integer.valueOf(pageText);
if(total%20==0){
pageTotal=total;
}else{
pageTotal=total/20+1;
}
for(int page=1;page<=pageTotal;page++){
String str=sb.toString()+"&p="+page;
collectIFeng(str,type);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public String jsoupHTML(String c,String b){
String subStr="";
try {
String baseURL = "http://v.yc.ifeng.com/remc.htm?";
StringBuffer paramsSB = new StringBuffer();
paramsSB.append("c=");
paramsSB.append(c);
paramsSB.append("&b=");
paramsSB.append(b);
String queryURL = baseURL+paramsSB.toString();
//获取json数据
String InboxJson = Jsoup.connect(queryURL).cookies(cookies).timeout(60 * 1000).ignoreContentType(true).maxBodySize(10 * 1024 * 1024).post().body().html();
InboxJson=InboxJson.replaceAll("\\\\", "");
System.out.println("采集的文章序号:"+"/"+c+"/"+b);
subStr=InboxJson.substring(12,InboxJson.lastIndexOf("<br>"));
return subStr;
} catch (Exception e) {
e.printStackTrace();
}
return subStr;
}
public void collectIFeng(String params,int type){
String urlIFeng="http://v.yc.ifeng.com";//进入凤凰网址url
String typeUrl=urlIFeng+params;//全路径
Document document=null;
String fileName="";
try {
document=Jsoup.connect(typeUrl).cookies(cookies).timeout(60 * 1000).ignoreContentType(true).maxBodySize(10 * 1024 * 1024).get();
Elements elements=document.select("ul[class=bimg]>li");
for(int i=0;i<elements.size();i++){
Element element=elements.get(i);
//获取详情url
String urlDetail=element.select("a").eq(0).attr("href");
//获取图片地址
String imgUrl=element.select("a>img").eq(0).attr("src");
fileName=this.saveImage(imgUrl,imagePath);
//通过详情页拿到每一个章节信息
String detailUrl=urlIFeng+urlDetail;
if(type==2){
this.connDetail(detailUrl,fileName,type);
}else{
this.connDetail(detailUrl,fileName);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
//解析原创书库详情页
private void connDetail(String detailUrl, String imageName,int type) {
String channelId="";//栏目id
String title="";//题名
String author="";//作者
String press="";//出版社
String classification="";//分类
String keyWords="";//关键词
String ab="";//简介
Document document=null;
try {
channelId=detailUrl.substring(detailUrl.lastIndexOf("/")+1, detailUrl.lastIndexOf("."));
document=Jsoup.connect(detailUrl).cookies(cookies).timeout(60 * 1000).ignoreContentType(true).maxBodySize(10 * 1024 * 1024).get();
Elements elements=document.select(".Bdescript2").eq(0);
document.select(".Bdescript2").eq(0).select("h2").eq(0).text();
title=elements.select("h2").eq(0).text();
Elements tab=elements.select("table>tbody>tr>td");
author=tab.eq(0).select("a").text();
press=tab.eq(2).select("a").text();
//classification=tab.eq(4).select("a").text();
keyWords=tab.eq(7).select("a").text();
ab=document.select(".paddbot").text();
//读取一条存入数据库一条
Elements eleChapter=document.select("#chapters_div");
//存入数据库操作
WriteToDateBase.insertChannel(channelId,title,author,press,classification,keyWords,ab,imageName);
//有章节是
if(!eleChapter.select("dd").isEmpty()){
//存入一个数据库
this.chapterDetail(eleChapter,channelId);
}
} catch (IOException e) {
e.printStackTrace();
}
}
//解析详情页
private void connDetail(String detailUrl,String imageName) {
String channelId="";//栏目id
String title="";//题名
String author="";//作者
String press="";//出版社
String classification="";//分类
String keyWords="";//关键词
String ab="";//简介
Document document=null;
try {
channelId=detailUrl.substring(detailUrl.lastIndexOf("/")+1, detailUrl.lastIndexOf("."));
document=Jsoup.connect(detailUrl).cookies(cookies).timeout(60 * 1000).ignoreContentType(true).maxBodySize(10 * 1024 * 1024).get();
Elements elements=document.select(".Bdescript").eq(0);
document.select(".Bdescript").eq(0).select("h2").eq(0).text();
title=elements.select("h2").eq(0).text();
Elements tab=elements.select("table>tbody>tr>td");
author=tab.eq(0).select("a").text();
press=tab.eq(1).select("a").text();
classification=tab.eq(4).select("a").text();
keyWords=tab.eq(8).select("a").text();
ab=elements.select("p").last().text();
//读取一条存入数据库一条
Elements eleChapter=document.select("#chapters_div");
//存入数据库操作
WriteToDateBase.insertChannel(channelId,title,author,press,classification,keyWords,ab,imageName);
//有章节是
if(!eleChapter.select("dd").isEmpty()){
//存入一个数据库
this.chapterDetail(eleChapter,channelId);
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 读取没一章节的详细内容
* @param eleChapter
* @param channelId
*/
private void chapterDetail(Elements eleChapter, String channelId) {
String urlIFeng="http://v.yc.ifeng.com";//进入凤凰网址url
String typeAB="";//分类型章节
String chapter="";//章节
String chapterId="";//章节id
String chapterContent="";//章节内容
Elements elements=eleChapter.select("dd");
for(int i=0;i<elements.size();i++){
Element element=elements.get(i);
typeAB=element.select("h5").text();
Elements elemeA=element.select("a");
for(int j=0;j<elemeA.size();j++){
//获取href的最后一个数字
String href=elemeA.get(j).attr("href");
chapter=elemeA.get(j).text();
String c=href.substring(href.lastIndexOf("/")+1,href.lastIndexOf("."));
chapterId=c;
String b=channelId;
chapterContent=this.jsoupHTML(c,b);
//存入数据库
WriteToDateBase.insertContent(channelId,chapterId,typeAB,chapter,chapterContent);
}
}
}
//存入文件获取文件名称,存图片
public String saveImage(String imgUrl,String imagePath) throws IOException{
// 构造URL
URL url = new URL(imgUrl);
String filename=imgUrl.substring(imgUrl.lastIndexOf("/")+1,imgUrl.length());
// 打开连接
URLConnection con=null;
InputStream is=null;
try {
con = url.openConnection();
//设置请求超时为5s
con.setConnectTimeout(5*1000);
// 输入流
is = con.getInputStream();
} catch (Exception e) {
//图片不存在时,调用默认图片
con =new URL("http://res.read.ifeng.com/images/book/book.jpg").openConnection();
con.setConnectTimeout(5*1000);
is = con.getInputStream();
}
// 1K的数据缓冲
byte[] bs = new byte[1024];
// 读取到的数据长度
int len;
// 输出的文件流
File sf=new File(imagePath);
if(!sf.exists()){
sf.mkdirs();
}
OutputStream os = new FileOutputStream(sf.getPath()+"\\"+filename);
// 开始读取
while ((len = is.read(bs)) != -1) {
os.write(bs, 0, len);
}
// 完毕,关闭所有链接
os.close();
is.close();
return filename;
}
}
Elements这个对象提供了一系列类似于DOM的方法来查找元素,抽取并处理其中的数据。具体如下:
查找元素
getElementById(String id)
getElementsByTag(String tag)
getElementsByClass(String className)
getElementsByAttribute(String key) (and related methods)
Element siblings: siblingElements(), firstElementSibling(), lastElementSibling();nextElementSibling(), previousElementSibling()
Graph: parent(), children(), child(int index)
元素数据
attr(String key)获取属性attr(String key, String value)设置属性
attributes()获取所有属性
id(), className() and classNames()
text()获取文本内容text(String value) 设置文本内容
html()获取元素内HTMLhtml(String value)设置元素内的HTML内容
outerHtml()获取元素外HTML内容
data()获取数据内容(例如:script和style标签)
tag() and tagName()
操作HTML和文本
append(String html), prepend(String html)
appendText(String text), prependText(String text)
appendElement(String tagName), prependElement(String tagName)
html(String value)
Selector选择器概述
tagname: 通过标签查找元素,比如:a
ns|tag: 通过标签在命名空间查找元素,比如:可以用 fb|name 语法来查找 元素
id: 通过ID查找元素
.class: 通过class名称查找元素,比如:.masthead