Jsoup的使用

  • 0. Jsoup介绍
  • 1. Get请求
  • 2. Post请求
  • 3. 通过document获取元素
  • 4. 练习Demo
    • 练习1
    • 练习2:获取所有图片
    • 练习3获取商品
    • 练习4 下载图片
  • 5. @PostConstruct

0. Jsoup介绍

jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。

org.jsoup.Jsoup类

方法 描述
static Connection connect(String url) 创建并返回URL的连接。
static Document parse(File in, String charsetName) 将指定的字符集文件解析成文档。
static Document parse(String html) 将给定的html代码解析成文档。
static String clean(String bodyHtml, Whitelist whitelist) 从输入HTML返回安全的HTML,通过解析输入HTML并通过允许的标签和属性的白名单进行过滤。

org.jsoup.nodes.Document类

修饰符和类型 方法 描述
Connection connection() 返回用于获取此文档的连接(请求/响应)对象(如果有);否则,一个新的默认 Connection 对象。
Document connection(Connection connection) 设置用于获取此文档的连接。

org.jsoup.nodes.Element类

修饰符和类型 方法 描述
Element child(int index) 通过从 0 开始的索引号获取此元素的子元素。
int childNodeSize() 获取该节点拥有的子节点数。
Elements children() 获取此元素的子元素。
int childrenSize() 获取此元素的子节点的数量。
String className() 获取此元素的“类”属性的字面值,其中可能包含多个类名,以空格分隔。
Set classNames() 获取所有元素的类名。
String cssSelector() 获取将唯一选择此元素的 CSS 选择器。
String data() 获取该元素的组合数据。
Elements getAllElements() 查找此元素下的所有元素(包括 self 和 children 的 children)。
Element getElementById(String id) 按 ID 查找元素,包括或在此元素下。
Elements getElementsByAttribute(String key) 查找具有命名属性集的元素。
Elements getElementsByAttributeStarting(String keyPrefix) 查找属性名称以提供的前缀开头的元素。
Elements getElementsByAttributeValue(String key, String value) 查找具有特定值的属性的元素。
Elements getElementsByAttributeValueContaining(String key, String match) 查找具有其值包含匹配字符串的属性的元素。
Elements getElementsByAttributeValueEnding(String key, String valueSuffix) 查找具有以值后缀结尾的属性的元素。
Elements getElementsByAttributeValueMatching(String key, String regex) 查找具有其值与提供的正则表达式匹配的属性的元素。
Elements getElementsByAttributeValueMatching(String key, Pattern pattern) 查找具有其值与提供的正则表达式匹配的属性的元素。
Elements getElementsByAttributeValueNot(String key, String value) 查找不具有此属性或具有不同值的元素。
Elements getElementsByAttributeValueStarting(String key, String valuePrefix) 查找具有以值前缀开头的属性的元素。
Elements getElementsByClass(String className) 查找具有此类的元素,包括或在此元素下。
Elements getElementsByIndexEquals(int index) 查找兄弟索引等于提供的索引的元素。
Elements getElementsByIndexGreaterThan(int index) 查找兄弟索引大于提供的索引的元素。
Elements getElementsByIndexLessThan(int index) 查找同级索引小于提供的索引的元素。
Elements getElementsByTag(String tagName) 查找具有指定标记名称的元素,包括并递归地在此元素下。
Elements getElementsContainingOwnText(String searchText) 查找直接包含指定字符串的元素。
Elements getElementsContainingText(String searchText) 查找包含指定字符串的元素。
Elements getElementsMatchingOwnText(String regex) 查找其自身文本与提供的正则表达式匹配的元素。
Elements getElementsMatchingOwnText(Pattern pattern) 查找其自身文本与提供的正则表达式匹配的元素。
Elements getElementsMatchingText(String regex) 查找其文本与提供的正则表达式匹配的元素。
Elements getElementsMatchingText(Pattern pattern) 查找其文本与提供的正则表达式匹配的元素。
Elements select(String cssQuery) 查找与SelectorCSS 查询匹配的元素,并以该元素作为起始上下文。

1. Get请求


// 方式一
Document document = Jsoup.connect("http://www.baidu.com/").get();
// 方式二
Document parse = Jsoup.parse(new URL("http://www.baidu.com/"), 3000);//3秒

2. Post请求

Document doc = Jsoup.connect("http://example.com").data("query", "Java").userAgent("Mozilla").cookie("auth", "token").timeout(3000).post();

3. 通过document获取元素

 getElementById(String id):通过id来获取getElementsByTag(String tagName):通过标签名字来获取getElementsByClass(String className):通过类名来获取getElementsByAttribute(String key):通过属性名字来获取getElementsByAttributeValue(String key, String value):通过指定的属性名字,属性值来获取getAllElements():获取所有元素

4. 练习Demo

练习1

File input = new File("/tmp/input.html");
Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/");Elements links = doc.select("a[href]"); //带有href属性的a元素
Elements pngs = doc.select("img[src$=.png]");//扩展名为.png的图片Element masthead = doc.select("div.masthead").first();//class等于masthead的div标签Elements resultLinks = doc.select("h3.r > a"); //在h3元素之后的a元素

练习2:获取所有图片

     Document documents = Jsoup.parse(new URL(url),3000);Elements images = document.select("img[src~=(?i)\\.(png|jpe?g|gif)]");for (Element image : images){System.out.println("src : " + image.attr("src"));System.out.println("height : " + image.attr("height"));System.out.println("width : " + image.attr("width"));System.out.println("alt : " + image.attr("alt"));}

练习3获取商品

package test;import entity.Commodity;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;/*** 获取商品信息* @author 有多勉为其难* @version 1.0.0* @date 2022/9/6*/
public class HtmlParseUtils {public static void main(String[] args) throws Exception {new HtmlParseUtils().getCommodity("鞋子", 10000).forEach(System.out::println);}private List<Commodity> getCommodity(String keyword, int timeout) throws IOException {//设置url编码String keywords = URLEncoder.encode(keyword,"utf-8");String url = "https://search.jd.com/Search?keyword="+keywords;Document document = Jsoup.parse(new URL(url), timeout);Element element = document.getElementById("J_goodsList");Elements liElements = element.getElementsByTag("li");List<Commodity> commodityList = new ArrayList<>();for (Element el : liElements) {String img = el.getElementsByTag("img").eq(0).attr("data-lazy-img").trim();String price = el.getElementsByClass("p-price").eq(0).text().trim();String name = el.getElementsByClass("p-name").eq(0).text().trim();Commodity commodity = new Commodity();commodity.setName(name);commodity.setImg(img);commodity.setPrice(price);commodityList.add(commodity);}return commodityList;}
}
package entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** 商品实体类* @author 有多勉为其难* @version 1.0.0* @date 2022/9/6*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Commodity {private String name;private String img;private String price;
}

练习4 下载图片

package test;import entity.Image;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import utils.DownloadUtils;import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;/*** 找到并下载图片** @author 有多勉为其难* @date 2022/9/6*/
public class DownloadImagesUtils {public static void main(String[] args) throws IOException {String url = "https://www.quanjing.com/creative/topic/1";downloadImage(url, "a");}private static void downloadImage(String url, String keyword) throws IOException {//设置url编码String keywords = URLEncoder.encode(keyword, "utf-8");Document doc = Jsoup.parse(new URL(url + keywords), 3000);Element element = doc.getElementById("gallery-list");Elements elements = element.getElementsByTag("li");List<Image> imageList = new ArrayList<>();List<String> urlList = new ArrayList<>();for (Element imgElement : elements) {String src = imgElement.getElementsByTag("img").eq(0).attr("src");String alt = imgElement.getElementsByTag("alt").eq(0).attr("alt");Image image = new Image();image.setAlt(alt);image.setSrc(src);imageList.add(image);urlList.add(src);}System.out.println(imageList);System.out.println(urlList);DownloadUtils.processSync(urlList, keyword);}
}
package utils;import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;/*** 图片下载工具类** @author 有多勉为其难* @version 1.0.0* @date 2022/9/6*/
public class DownloadUtils {private String extension = ".jpg";private String path;private static volatile AtomicInteger suc;private static volatile AtomicInteger fails;public DownloadUtils() {setPath("E:/pipeline/");suc = new AtomicInteger();fails = new AtomicInteger();}public void setPath(String path) {this.path = path;}/*** 下载** @param url* @param cate* @throws Exception*/private void downloadImg(String url, String cate, String name) throws Exception {String path = this.path + "/" + cate + "/";File dir = new File(path);if (!dir.exists()) {    // 目录不存在则创建目录dir.mkdirs();}// 获取扩展名String realExt = url.substring(url.lastIndexOf("."));String fileName = name + realExt;fileName = fileName.replace("-", "");String filePath = path + fileName;File img = new File(filePath);// 若文件之前已经下载过,则跳过if (img.exists()) {System.out.println(String.format("文件%s已存在本地目录", fileName));return;}URLConnection con = new URL(url).openConnection();con.setConnectTimeout(5000);con.setReadTimeout(5000);InputStream inputStream = con.getInputStream();byte[] bs = new byte[1024];File file = new File(filePath);FileOutputStream os = new FileOutputStream(file, true);// 开始读取 写入int len;while ((len = inputStream.read(bs)) != -1) {os.write(bs, 0, len);}System.out.println("picUrl: " + url);System.out.println(String.format("正在下载第%s张图片", suc.getAndIncrement()));}/*** 多线程处理** @param data* @param word*/public static void processSync(List<String> data, String word) {long start = System.currentTimeMillis();int count = 0;DownloadUtils downloadUtils = new DownloadUtils();// 创建缓存线程池/*优点:线程池会根据任务数量创建线程池,并且在一定时间内可以重复使用这些线程,产生相应的线程池。缺点:适用于短时间有大量任务的场景,它的缺点是可能会占用很多的资源。*/ExecutorService executorService = Executors.newCachedThreadPool();
//        ThreadPoolExecutor executorService = new ThreadPoolExecutor(5, 10, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100));for (int i = 0; i < data.size(); i++) {String picUrl = data.get(i);if (picUrl == null) {continue;}String name = "";if (i < 10) {name = "000" + i;} else if (i < 100) {name = "00" + i;} else if (i < 1000) {name = "0" + i;}String finalName = name;executorService.execute(() -> {try {downloadUtils.downloadImg(picUrl, word, finalName);} catch (Exception e) {//                    e.printStackTrace();DownloadUtils.fails.incrementAndGet();}});count++;}executorService.shutdown();try {if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {// 超时的时候向线程池中所有的线程发出中断(interrupted)。//                executorService.shutdownNow();}System.out.println("AwaitTermination Finished");System.out.println("共有URL: " + data.size());System.out.println("下载成功: " + suc);System.out.println("下载失败: " + fails);File dir = new File(downloadUtils.path + "/" + word + "/");int len = Objects.requireNonNull(dir.list()).length;System.out.println("当前共有文件: " + len);long end = System.currentTimeMillis();System.out.println("耗时:" + (end - start) / 1000.0 + "秒");} catch (InterruptedException e) {e.printStackTrace();}}}

5. @PostConstruct

@PostConstruct是Java自带的注解,在方法上加该注解会在项目启动的时候执行该方法,也可以理解为在spring容器初始化的时候执行该方法。

@SpringBootApplication
@ComponentScan(basePackages = {"com.my.spider"})
@MapperScan("com.my.spider.mapper")
public class MySpiderApplication {@Autowiredprivate SpiderHandle spiderHandle;@Autowiredprivate ContentNoticeHandle contentNoticeHandle;public static void main(String[] args) {SpringApplication.run(MySpiderApplication.class, args);}@PostConstructpublic void task(){contentNoticeHandle.spiderData();}/*@PostConstructpublic void task(){spiderHandle.spiderData();}
*/
}

Java爬虫Jsoup的使用相关推荐

  1. java爬虫---Jsoup

    简单易懂的java爬虫-Jsoup 做个简单的Demo,爬取酒店的基本信息,酒店名称.酒店地址.酒店星级.酒店的图片等.这里考虑在哪个网站爬取这些数据呢?第一个想到的就是X程上. Jsoup爬取的是网 ...

  2. java爬虫(jsoup)实现搜狗图片一键下载

    java爬虫(jsoup)实现搜狗图片一键下载 import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.no ...

  3. java爬虫解析script_详解java爬虫jsoup解析多空格class数据

    在使用jsoup爬取其他网站数据的时候,发现class是带空格的多选择,如果直接使用doc.getElementsByClass("class的值"),这种方法获取不到想要的数据. ...

  4. 采集 58同城 房产数据信息 | Java爬虫 Jsoup

    一个数据采集系统(通俗的说就是爬虫),用来采集 58同城 房产 | 郑州中的房屋数据.使用 Java 语言和Jsoup库编写,这里分享给大家. 最后采集的数据结果 CSV 文件保存的,如下所示 说明 ...

  5. java jsoup 网络爬虫 jsoup解析html Java爬虫 Jsoup爬虫 jsoup例子

    java jsoup 网络爬虫 java jsoup 网络爬虫 学习例子(一)抓取豆瓣电影名称+推荐星级 java jsoup 网络爬虫 学习例子(二)只抓取豆瓣电影5星(力荐)电影名称 java j ...

  6. JAVA爬虫Jsoup,抓取房价

    里面的命名很烂,但能跑出来效果. 依赖: <!-- https://mvnrepository.com/artifact/org.jsoup/jsoup --> <dependenc ...

  7. Java爬虫Jsoup简易使用

    一.准备工作 1.下载jsoup工具,如果是maven项目,请在pm.xml中加入以下代码: jsoup虽然不是一个很强大的爬虫工具,但是它对于网页html文档的各种处理确实是很强大的,同时自身也是个 ...

  8. JAVA爬虫-Jsoup + JsoupXPath

    JsoupXPath是基于Jsoup的拓展,使用路径的形式解析XML和HTML文档.核心类为JXDocument.JsoupXPath的节点对象JXNode不仅可以获取标签节点,还可以获取属性节点. ...

  9. Java爬虫之利用Jsoup自制简单的搜索引擎

      Jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址.HTML文本内容.它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据.Jso ...

最新文章

  1. DK云网关与普通DTU之间的区别
  2. Redis 禁止使用耗时命令和时间复杂度为O(n)的命令
  3. CentOS 7 根目录分区扩容
  4. 方舟生存进化手游服务器显示以驯养两千,《方舟:生存进化》手游官方网站-大型生存探索沙盒手游...
  5. ubuntu20.04装机教程
  6. java排座位程序_java随机排座位
  7. Linux系统之audit
  8. ABAP ONF4 事件 查找表
  9. JS 下载 URL 链接文件(点击按钮、点击a标签、支持代理与非代理下载)
  10. Android解决输入法自动弹出方法大全
  11. postman设置前置条件
  12. 米家和HomeKit等智能家居联动的重要性
  13. 网罗全网最优质AI社区!
  14. 线程什么状态时候会被挂起?挂起是否也是一个状态?
  15. Java学习笔记——流程控制
  16. 从spaceX的火箭回收想到的一些事儿
  17. 京东详情页批量关联海报,提高转化80%
  18. 优化大师每天定点自动优化脚本
  19. C# SQL Server笔记
  20. 回转半径的计算公式_一种计算船舶回转半径的方法

热门文章

  1. PyQt5 QtChart-曲线图
  2. python jsonpath模块
  3. vue项目获取下拉框选中id_vue获取下拉框值
  4. Docker 修改容器端口
  5. 基础编程题目集(15 分题)
  6. java类图与代码实例
  7. 中山大学HCP Lab系列论文:AI解题新突破,神经网络推开数学推理大门
  8. 06-02 标签管理
  9. SpringBoot整合rabbitmq使用案例
  10. 3238: [Ahoi2013]差异