使用Jsoup抓取京东图书分类页面图书信息

时间:2021-08-16 20:40:44

一、目的:

1.任务

使用 Jsoup抓取京东图书分类页面的图书信息。
抓取目标分类网址例如:https://list.jd.com/list.html?cat=1713,3259,3330
给与的某个图书页面,抓取每一页面的图书信息,此分类页多页抓取直至结束。

下面图片即为给定目标抓取页面地址
https://list.jd.com/list.html?cat=1713,3259,3330
使用Jsoup抓取京东图书分类页面图书信息

我们获取到的应该是每一本图书里边的图书信息,类似模拟打开了网页查阅了图书信息内容。
所以我们随便打开一个item(红框圈了,暂且把分类页面的一本图书视为一个item吧),查看内容。
抓取内容是红框里这一部分:
使用Jsoup抓取京东图书分类页面图书信息

2.工具和语言

语言:java
工具:jsoup-1.7.2.jar

二、思路

我们采取这样的思路,
1.将分类网站源码保存到本地
2.解析出分类页面所有的图书(item)拿到一个类似的item的List集合
3.根据拿到的List集合,遍历循环去解析每个页面中的图书信息,匹配到图书信息控制台打印即可。

我们把抓取京东图书抽象成一个类,这个类有保存下载源码的方法,有解析分类页面拿到List集合的方法,有解析图书页面信息的方法等。

三、解析

1.将分类网站源码保存到本地

将网站的源码下载到本地的方法,这样在本地就可以看到一个text文件, 专门存放当前网站源码的txt文件。用来解析使用的

/**
* 将目标html保存到本地中进行解析获得 doc文本对象
* @param htmlUrl 需要下载到本地的网址
* @param toSavePath 需要保存到本地的电脑路径 例如E:\\jd.txt
* @param type 编码方式 UTF-8 或者 GBK 等
* @return
* @throws IOException
*/

public Document getDocFromUrl(String htmlUrl,String toSavePath,String type) throws IOException
{
URL url = new URL(htmlUrl) ;

File file = new File(toSavePath) ;
if(file.exists())
file.delete() ;
file.createNewFile() ;

FileOutputStream fos = new FileOutputStream(file) ;

BufferedReader br = new BufferedReader(
new InputStreamReader(url.openStream(),type)) ;

byte [] b = new byte[1024] ;
String c ;
while(((c = br.readLine())!=null))
{
fos.write(c.getBytes());
}

System.out.println("保存分类html完毕");

Document doc = Jsoup.parse(file,"UTF-8") ;

return doc ;
}

2.解析出分类页面所有的图书

这里就是解析出分类页面中的所有如图所示的item 的每个地址,将他们的地址变成一个List集合即可。这样就获得了当前某一页的所有的图书地址。为解析每个图书信息做一个铺垫。

打开浏览器的开发者模式(F12)看一下如何解析:
我们在图书信息列表中不难发现这些每一本图书都是由Li标签包裹,这些图书li标签都被使用一个class=“gl-warp”的ul的包裹着,分析到这你应该就有思路了。
这种情况我们先使用jsoup拿到ul标签的内容,再对ul标签里的li标签进行getElementsByTag(“li”); 方法,这样拿到的是每一个li标签的内容,也就是每个图书的内容。 以下两行代码获取到li的集合

    Element contentEl = doc.select("ul.gl-warp").first() ;
Elements lis = contentEl.getElementsByTag("li");

使用Jsoup抓取京东图书分类页面图书信息

拿到图书们的Elements元素还没完因为我们要的是这些图书的地址,换句话说要的是图书List< String > 但是如何解析出每个图书的地址呢 我们需要随便打开某个li标签进行查看。

使用Jsoup抓取京东图书分类页面图书信息

也许你一眼就看到了一个地址,没错,就是这个标签。我们再拿到它的href属性值就行了,任性
如何做 :
Element titleEl = li.select(“div.p-name”).first() ;
Element a = titleEl.select(“a”).first() ;
String href = a.attr(“href”) ;

啰嗦了这么多上代码 看一眼:


/**
* 解析每一个图书的页面地址
* @param doc
* @return
*/

public List<String> parseItemUrl(Document doc)
{
//获取页面
Element contentEl = doc.select("ul.gl-warp").first() ;
Elements lis = contentEl.getElementsByTag("li");
for (Element li : lis) {
//for循环的就是每一本书拿到详情地址
Element titleEl = li.select("div.p-name").first() ;
Element a = titleEl.select("a").first() ;
String href = a.attr("href") ;
href = "http:"+href ;
hrefList.add(href) ;
}
return hrefList ;

}

3.解析一本图书

解析每一本图书,根据该图书详情页的地址,下载此详情页源码,去使用jsoup匹配。可以看到图片中高亮的部分就是我们要解析的内容。同样很清晰,我们只需要解析到 一个叫class = ”parameter2 ”ul标签, 然后再对里边每个li进行解析就ok了 ,思路完全可以按照上一个解析过程来。 这里我是直接当成一个text文本全部输出出来了,没有循环遍历具体到每一个li标签, 大家可以完全按照上一个来做。

使用Jsoup抓取京东图书分类页面图书信息

    /**
* 解析书本的信息
* @param doc
*/

public void parseContent(Document doc)
{
Element contentEl = doc.getElementById("parameter2") ;
if(contentEl==null)
return ;

Elements lis = contentEl.getElementsByTag("li");

if(lis==null)
return ;

for (Element li : lis) {
String text = li.text() ;
System.out.println("--"+text);
}
}

解析当前分类页的下一页的内容

我们需要的就是匹配到当前页面的下一页的按钮的规则,获取下一页的url即可。
使用Jsoup抓取京东图书分类页面图书信息

解析下一页的按钮也不难发现 我们要找到 p-num 的span标签, 然后在此标签内找到pn-next的 a标签。 该a标签的href属性值就是我们要找到的地址。
这里我们就直接通过代码来拿到他。

使用Jsoup抓取京东图书分类页面图书信息

    /**
* 解析下一页
* @param doc
* @return
*/

public String parseNext(Document doc)
{ String nextPageHref="";

Element el = doc.select("span.p-num").first() ;
Elements as = el.getElementsByTag("a") ;
for(Element a :as)
{

if(a.attr("class").endsWith("pn-next"))
{
String pageHref = a.attr("href") ;
nextPageHref = htmlUrl.substring(0,htmlUrl.lastIndexOf("/"))+pageHref;
System.out.println("下一页地址:"+nextPageHref);
}
}
return nextPageHref;
}

四、代码:

封装的解析类HtmlParser .java:

package com.jd.test;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
/**
* html网址解析器
* @author shaoduo
*
*/

public class HtmlParser {

String htmlUrl = "" ;
String nextPageUrl = "" ;
String charSet = "" ;


List<String> hrefList = new ArrayList<String>() ;


public HtmlParser(String htmlUrl)
{
this.htmlUrl = htmlUrl ;
}

/* public List<String> getHrefList ()
{
try {

parser() ;

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

return hrefList ;
}*/



public String getNextPageHrefList()
{

return this.nextPageUrl ;
}


/**
* 解析过程
* @param htmlUrl
* @throws IOException
*/

public void parser(String htmlUrl) throws IOException {

Document doc = getDocFromUrl(htmlUrl, "D:\\cat.txt","utf-8") ;
hrefList = parseItemUrl(doc) ;
for (String string : hrefList) {
Document conDoc = getDocFromUrl(string, "D:\\content.txt","gbk") ;
parseContent(conDoc);
}

nextPageUrl = parseNext(doc) ;
if(nextPageUrl!="")
{
System.out.println("解析下一页------------");
parser(nextPageUrl) ;
}

}



/**
* 将目标html保存到本地中进行解析获得 doc文本对象
* @param htmlUrl
* @param toSavePath
* @param type
* @return
* @throws IOException
*/

public Document getDocFromUrl(String htmlUrl,String toSavePath,String type) throws IOException
{
URL url = new URL(htmlUrl) ;

File file = new File(toSavePath) ;
if(file.exists())
file.delete() ;
file.createNewFile() ;

FileOutputStream fos = new FileOutputStream(file) ;

BufferedReader br = new BufferedReader(
new InputStreamReader(url.openStream(),type)) ;

byte [] b = new byte[1024] ;
String c ;
while(((c = br.readLine())!=null))
{
fos.write(c.getBytes());
}

System.out.println("保存分类html完毕");

Document doc = Jsoup.parse(file,"UTF-8") ;

return doc ;
}


/**
* 解析每一个图书的页面地址
* @param doc
* @return
*/

public List<String> parseItemUrl(Document doc)
{
//获取页面
Element contentEl = doc.select("ul.gl-warp").first() ;
Elements lis = contentEl.getElementsByTag("li");
for (Element li : lis) {

Element titleEl = li.select("div.p-name").first() ;
Element a = titleEl.select("a").first() ;
String href = a.attr("href") ;
href = "http:"+href ;
hrefList.add(href) ;
}
return hrefList ;

}

/**
* 解析书本的信息
* @param doc
*/

public void parseContent(Document doc)
{
Element contentEl = doc.getElementById("parameter2") ;
if(contentEl==null)
return ;

Elements lis = contentEl.getElementsByTag("li");

if(lis==null)
return ;

for (Element li : lis) {
String text = li.text() ;
System.out.println("--"+text);
}
}

/**
* 解析下一页
* @param doc
* @return
*/

public String parseNext(Document doc)
{ String nextPageHref="";

Element el = doc.select("span.p-num").first() ;
Elements as = el.getElementsByTag("a") ;
for(Element a :as)
{

if(a.attr("class").endsWith("pn-next"))
{
String pageHref = a.attr("href") ;
nextPageHref = htmlUrl.substring(0,htmlUrl.lastIndexOf("/"))+pageHref;
System.out.println("下一页地址:"+nextPageHref);
}
}
return nextPageHref;
}




}

测试类程序主入口:

package com.jd.test;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

/**
* 京东图书分类html网址解析主入口
* @author shaoduo
*
*/

public class JD {


static List<String> hrefList = new ArrayList<String>() ;
static String nextPageUrl = "" ;


public static void main(String arg[])
{

String startCatUrl = "https://list.jd.com/list.html?cat=1713,3279,3646";

HtmlParser hp = new HtmlParser(startCatUrl) ;
try {

hp.parser(startCatUrl);

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

五、源代码下载

https://github.com/shaoduo123/JD_CAT_JOUP_DEMO


版权声明
author :shaoduo
原文来自:http://blog.csdn.net/shaoduo/article/details/78247664
其他出处均为转载,原创作品,欢迎读者批评指正。