整个页面
与httpclient无异
/**
* 爬取网页
* @throws IOException
* */
@Test
public void testt_01() throws IOException {
String url = "http://www.jd.com";
Connection connect = Jsoup.connect(url);
Response execute = connect.execute();
System.out.println(execute.body());
}
整个网站
使用jsoup定位a标签 , 获取所有a标签 , 然后获取href的值
/**
* 爬取整个网站
* @throws IOException
* */
@Test
public void test_02() throws IOException {
String url = "http://www.jd.com";
Document document = Jsoup.connect(url).get();
//寻找a标签
Elements elementsByTag = document.getElementsByTag("a");
for(Element element :elementsByTag) {
String href = element.attr("href");
String val = element.val();
System.out.println("连接地址:"+href + "---"+val);
}
}
定位信息
/**
* 爬取一个网页中的信息
* 定位具体标签中的数据
* @throws IOException
* */
@Test
public void test_03() throws IOException {
String url= "http://item.jd.com/4329035.html";
//get请求 获取的是返回结构的document树
//excute获取的是返回的所有数据
Document doc = Jsoup.connect(url).get();
//选择器与jQ中的选择器使用一致
//为了 定位准确 , 使用父子选择器 , 确定唯一的定位
Element select = doc.select("ul li .p-img a").get(0);
System.out.println(select.attr("href"));
}
json二次提交获取信息
需要自己 寻找页面中发起 ajax的请求地址
/**
* 抓取二次提交
* 商品价格是页面加载之后又通过ajax获取的
* @throws IOException
* */
@Test
public void test_04() throws IOException {
String url = "http://p.3.cn/prices/mgets?skuIds=J_5089253";
Response response = Jsoup.connect(url).ignoreContentType(true).execute();
String json = response.body();
System.out.println(json);
ObjectMapper mp = new ObjectMapper();
JsonNode jn = mp.readTree(json);
//[{"op":"8388.00","m":"9999.00","id":"J_5089253","p":"8388.00"}]
//直接获取到的是数组 ,需要获取到第一个元素
String price = jn.get(0).get("p").asText();
System.out.println(price);
}
jsonp数据
/**
* 获取jsonp请求数据
* @throws IOException
* */
@Test
public void test_05() throws IOException {
String url = "http://d.3.cn/desc/4329035";
String jsonDesc = Jsoup.connect(url).ignoreContentType(true).execute().body();
System.out.println(jsonDesc);
String data = jsonDesc.substring(jsonDesc.indexOf("(")+1, jsonDesc.lastIndexOf(")"));
System.out.println(data);
ObjectMapper mp = new ObjectMapper();
JsonNode jn = mp.readTree(data);
String desc = jn.get("date").asText();
System.out.println(desc);
}
爬取京东商品信息
/**
* 爬取京东商品的所有商品信息
* @author outman
* 2018 - 1 - 31 - 17:48
* 步骤:
* 1. 先获取所有的商品三级分类链接
* 2. 访问商品分类链接后获取一个分类下所有商品的链接(可能存在分页的情况)
* 3. 访问商品链接后获取商品信息
*
* 过程中要十分注意异常的处理
* 在爬取过程中一旦出现异常 , 后续的过程也将受到影响 , 导致整个数据错乱
* */
public class JDCrawler {
private static SqlSession session ;
static {
//获取一个数据流
InputStream in;
try {
in = Resources.getResourceAsStream("mybatis-config.xml");
//创建一个工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//创建一个会话
session = factory.openSession(true);//true表示自动提交 , 默认为false , 需要手动提交
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 入口函数
* @throws Exception
* */
public static void main (String[] args) throws Exception {
//测试
//http://www.jd.com/allSort.aspx 商品 分类页面
// getItemCatUrls("http://www.jd.com/allSort.aspx");
//list.jd.com/list.html?cat=12379,13302,13313 某一分类下的商品展示页面
// getItemsPageUrls("http://list.jd.com/list.html?cat=12379,13302,13313");
//http://list.jd.com/list.html?cat=12379,13302,13313&page=2 商品展示页面
// getItemUrls("http://list.jd.com/list.html?cat=12379,13302,13313&page=2");
//item.jd.com/12017077901.html 商品信息页面
// getItem("http://item.jd.com/12017077901.html");
// 12017077901某一个商品的ID
// getPrice(new Long("12017077901"));
//完整测试
List itemCatUrls = getItemCatUrls("http://www.jd.com/allSort.aspx");
for(String itemCaturl :itemCatUrls) {
System.out.println("商品分类链接:"+itemCaturl);
List itemsPageUrls = getItemsPageUrls(itemCaturl);
for(String itemsPageUrl : itemsPageUrls) {
System.out.println("商品展示页面链接:"+itemsPageUrl);
List itemUrls = getItemUrls(itemsPageUrl);
for(String itemUrl : itemUrls) {
System.out.println("商品链接:"+itemUrls);
Item item = getItem(itemUrl);
saveItem(item);
System.out.println(item);
}
}
}
}
/**
* 获取京东商品的所有分类链接
* @throws Exception
* */
public static List getItemCatUrls(String url) throws Exception{
//记录数据数量
Integer hrefPreNum = 0 ;
List itemCatUrls = new ArrayList();
//这里选择抛出异常 , 这里如果抛出异常 , 说明url有问题 , 或者网络有问题 , 后续的操作没有任何意义
Document doc = Jsoup.connect(url).get();
Elements eles = doc.select("dl dd a");
for(Element ele : eles) {
String href = ele.attr("href");
hrefPreNum += 1;
if(href.startsWith("//list.jd.com/")) {
itemCatUrls.add("http:"+href);
// System.out.println(href);
}
}
System.out.println("获取到的总三级分类链接量:"+hrefPreNum);
System.out.println("数据清洗后的数量:"+itemCatUrls.size());
return itemCatUrls;
}
/**
* 获取三级分类下所有商品页面的链接
* 商品展示可能存在分页的情况
* 所以在获取所有的商品链接之前需要先获取 所有的商品分类页
* */
public static List getItemsPageUrls(String url){
List itemsPages = new ArrayList();
//从商品展示页面获取分页信息
String num;
try {//抛出异常 , 如果 出现异常则继续执行 , 丢失一点信息是正常的
num = Jsoup.connect(url).get().select("#J_topPage span i").get(0).text();
Long numL = new Long(num);
for(int i = 1 ; i<=numL ; i++) {
String pageUrl = url+"&page="+i;
// System.out.println(pageUrl);
itemsPages.add(pageUrl);
}
} catch (Exception e) {
e.printStackTrace();
}
return itemsPages;
}
/**
* 获取每个商品分类页面的商品链接
* */
public static List getItemUrls(String url){
List itemUrls = new ArrayList();
try {
Elements eles = Jsoup.connect(url).get().select(" li div .p-img a");
for(Element ele : eles) {
String itemUrl = ele.attr("href");
itemUrls.add("http:"+itemUrl);
}
} catch (Exception e) {
System.out.println("获取商品展示页面的商品链接出错:"+url);
}
return itemUrls;
}
/**
* 访问商品链接 , 获取商品数据
* */
public static Item getItem (String url) {
Item item = new Item();
Long id = null;
try {
Document doc = Jsoup.connect(url).get();
//获取id //item.jd.com/12016709876.html
id = new Long(url.substring(url.lastIndexOf("/")+1, url.indexOf(".html")));
//获取title
String title = doc.select("#name h1").get(0).text();
//获取卖点 获取到的 值为"" 说明页面时是通过ajax方式请求 需要json格式的数据
// String sellPoint = doc.select("#p-ad").get(0).text();
String sellPoint = getSellPoint(id);
//获取价格 价格是通过ajax二次请求的
// Long price = new Long(doc.select(".dd .p-price .price").get(0).text());
Long price = getPrice(id);
//获取图片
// String img = doc.select("#spec-n1 img").attr("src");
String img = getImg(url);
// System.out.println(img);
//获取商品详情
// String desc = doc.select("J-detail-content").get(0).text();
String desc = getDesc(id);
//封装属性
item.setId(id);
item.setTitle(title);
item.setSellPoint(sellPoint);
item.setPrice(price);
item.setImg(img);
item.setDesc(desc);
System.out.println(item);
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("获取商品信息失败");
}
return item;
}
/**
* 爬取卖点
* 由于商品价格是页面加载完成之后 , 有通过ajax获取的 , 所以单独爬取json格式的数据
* 通过页面分析 得到卖点的url
* http://ad.3.cn/ads/mgets?skuids=AD_ +12017077901
* */
public static String getSellPoint(Long id) {
String sellPoint = null;
try {
Response resp = Jsoup.connect("http://ad.3.cn/ads/mgets?skuids=AD_"+id).ignoreContentType(true).execute();
ObjectMapper mapper = new ObjectMapper();
sellPoint = mapper.readTree(resp.body()).get(0).get("ad").asText();
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("获取卖点失败");
}
return sellPoint;
}
/**
* 爬取商品价格
* 由于商品价格是页面加载完成之后 , 有通过ajax获取的 , 所以单独爬取
* 通过页面分析 得到商品价格的链接 //p.3.cn/prices/get?skuid=id
* */
public static Long getPrice(Long id) {
Long price = null;
try {
Response resp = Jsoup.connect("http://p.3.cn/prices/get?skuid="+id).ignoreContentType(true).execute();
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNode = mapper.readTree(resp.body()).get(0);
price = jsonNode.get("m").asLong();
// System.out.println(price);
} catch (Exception e) {
System.out.println("获取价格失败");
}
return price;
}
/**
* 获取商品图片
* 通过分析页面 , 得到图片的请求地址
* */
public static String getImg(String url) {
String img = "";
Document doc;
try {
doc = Jsoup.connect(url).get();
//获取页面大图的地址
String bigsrc = doc.select("#spec-n1 img").attr("src");
// System.out.println("大图地址:"+bigsrc);
//获取小图地址
Elements smallsrcs = doc.select("#spec-list div ul li img");
for(Element ele : smallsrcs) {
String src = ele.attr("src");
// System.out.println("小图地址:"+src);
//将小图地址替换成大图
String newSrc = src.replace("n5", "n1");
img+=newSrc+";";
// System.out.println(newSrc);
}
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("获取图片失败");
}
img = img.substring(0 , img.length()-1);
return img;
}
/**
* 爬取商品详情
* 商品详情是页面加载完成之后 , 通过jsonp获取的 , 需要单独获取
* http://dx.3.cn/desc/10316672107
* */
public static String getDesc(Long id) {
String desc = null;
try {
Response resp = Jsoup.connect("http://dx.3.cn/desc/"+id).ignoreContentType(true).execute();
ObjectMapper mapper = new ObjectMapper();
String body = resp.body();
body = body.substring(body.indexOf("(")+1, body.lastIndexOf(")"));
desc = mapper.readTree(body).get("content").asText();
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("获取不到"+id+"的商品描述");
}
return desc;
}
/**
* 数据入库
* */
public static void saveItem(Item item) {
session.insert("ItemMapper.saveItem" , item);
}
}