Java爬虫Jsoup的使用
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的使用相关推荐
- java爬虫---Jsoup
简单易懂的java爬虫-Jsoup 做个简单的Demo,爬取酒店的基本信息,酒店名称.酒店地址.酒店星级.酒店的图片等.这里考虑在哪个网站爬取这些数据呢?第一个想到的就是X程上. Jsoup爬取的是网 ...
- java爬虫(jsoup)实现搜狗图片一键下载
java爬虫(jsoup)实现搜狗图片一键下载 import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.no ...
- java爬虫解析script_详解java爬虫jsoup解析多空格class数据
在使用jsoup爬取其他网站数据的时候,发现class是带空格的多选择,如果直接使用doc.getElementsByClass("class的值"),这种方法获取不到想要的数据. ...
- 采集 58同城 房产数据信息 | Java爬虫 Jsoup
一个数据采集系统(通俗的说就是爬虫),用来采集 58同城 房产 | 郑州中的房屋数据.使用 Java 语言和Jsoup库编写,这里分享给大家. 最后采集的数据结果 CSV 文件保存的,如下所示 说明 ...
- java jsoup 网络爬虫 jsoup解析html Java爬虫 Jsoup爬虫 jsoup例子
java jsoup 网络爬虫 java jsoup 网络爬虫 学习例子(一)抓取豆瓣电影名称+推荐星级 java jsoup 网络爬虫 学习例子(二)只抓取豆瓣电影5星(力荐)电影名称 java j ...
- JAVA爬虫Jsoup,抓取房价
里面的命名很烂,但能跑出来效果. 依赖: <!-- https://mvnrepository.com/artifact/org.jsoup/jsoup --> <dependenc ...
- Java爬虫Jsoup简易使用
一.准备工作 1.下载jsoup工具,如果是maven项目,请在pm.xml中加入以下代码: jsoup虽然不是一个很强大的爬虫工具,但是它对于网页html文档的各种处理确实是很强大的,同时自身也是个 ...
- JAVA爬虫-Jsoup + JsoupXPath
JsoupXPath是基于Jsoup的拓展,使用路径的形式解析XML和HTML文档.核心类为JXDocument.JsoupXPath的节点对象JXNode不仅可以获取标签节点,还可以获取属性节点. ...
- Java爬虫之利用Jsoup自制简单的搜索引擎
Jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址.HTML文本内容.它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据.Jso ...
最新文章
- DK云网关与普通DTU之间的区别
- Redis 禁止使用耗时命令和时间复杂度为O(n)的命令
- CentOS 7 根目录分区扩容
- 方舟生存进化手游服务器显示以驯养两千,《方舟:生存进化》手游官方网站-大型生存探索沙盒手游...
- ubuntu20.04装机教程
- java排座位程序_java随机排座位
- Linux系统之audit
- ABAP ONF4 事件 查找表
- JS 下载 URL 链接文件(点击按钮、点击a标签、支持代理与非代理下载)
- Android解决输入法自动弹出方法大全
- postman设置前置条件
- 米家和HomeKit等智能家居联动的重要性
- 网罗全网最优质AI社区!
- 线程什么状态时候会被挂起?挂起是否也是一个状态?
- Java学习笔记——流程控制
- 从spaceX的火箭回收想到的一些事儿
- 京东详情页批量关联海报,提高转化80%
- 优化大师每天定点自动优化脚本
- C# SQL Server笔记
- 回转半径的计算公式_一种计算船舶回转半径的方法