Directorio de artículos de la serie
Consultar el puntaje de calidad de un artículo a través de Java+Selenium Consultar
el puntaje de calidad de los 40 artículos principales de un blogger
a través de Java+Selenium Consultar el puntaje de calidad de los 100 artículos principales de un blogger a través de Java+Selenium
Directorio de artículos
- Directorio de artículos de la serie
- prefacio
- 1. Preparación ambiental
- 2. Consulta los 100 artículos principales de un determinado blogger
-
- 2.1 Modificar la configuración de pom.xml
- 2.2 Configure el controlador Chrome (clase SeleniumUtil, incluida la ubicación del controlador, la ruta para guardar la imagen)
- 2.3 Introducir la configuración del navegador
- 2.4 Establecer el modo sin cabeza
- 2.5 Inicie la instancia del navegador y agregue información de configuración
- 2.6 Configuración de la ventana
- 2.7, Prohibir cargar configuraciones de imagen
- 2.8 Cargar dirección de blogger
- 2.9 Cargar lista de artículos
- 2.10 Cargar la página siguiente
- 2.11 Configurar para cargar 100 piezas de datos
- 2.12 Optimizado el cambio frecuente del navegador Chrome
- 2.13 Resultados
- 3. Puntuación de calidad del artículo de consulta circular
- 4. Código
- Resumir
prefacio
Hola a todos, soy Qinghua. En este artículo, compartiré con ustedes "Consulta del puntaje de calidad de los 100 artículos principales de un blogger a través de Java+Selenium". Se ha realizado una optimización simple para los 40 artículos principales en el capítulo anterior . Cuando consultar el puntaje de calidad del blog, para controlar el cambio frecuente del navegador Chrome, evitando la carga repetida del controlador Chrome y la apertura del navegador Chrome.
Observaciones: En el capítulo anterior, al cargar 100 artículos, se restringirá el acceso cuando el número de artículos sea 50-60.
1. Preparación ambiental
Navegador: este artículo utiliza Chrome
Versión del navegador Chrome: 113
Versión del controlador de Chrome: 113 ( primer artículo del rastreador de Java )
Versión de Java: Jdk1.8
Versión de Selenium: 4.9.1
2. Consulta los 100 artículos principales de un determinado blogger
2.1 Modificar la configuración de pom.xml
<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.3</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.9.1</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
2.2 Configure el controlador Chrome (clase SeleniumUtil, incluida la ubicación del controlador, la ruta para guardar la imagen)
/***
* @title SeleniumUtil
* @desctption Selenium辅助类
* @author Kelvin
* @create 2023/6/21 22:47
**/
@Slf4j
public class SeleniumUtil {
public final static String CHROMEDRIVERPATH = "/Users/apple/Downloads/chromedriver_mac64/chromedriver";
public final static String LOCATION_IMG_BASE_PATH = "~/java/code/spiderX/img/";
public static void sleep(int m) {
try {
Thread.sleep(m);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.setProperty("webdriver.chrome.driver", SeleniumUtil.CHROMEDRIVERPATH );// chromedriver localPath
2.3 Introducir la configuración del navegador
WebDriver driver;
ChromeOptions chromeOptions = new ChromeOptions();
2.4 Establecer el modo sin cabeza
chromeOptions.addArguments('--headless')
chromeOptions.addArguments("--remote-allow-origins=*");
2.5 Inicie la instancia del navegador y agregue información de configuración
driver = new ChromeDriver(chromeOptions);
2.6 Configuración de la ventana
chromeOptions.addArguments("–no-sandbox"); //--start-maximized
2.7, Prohibir cargar configuraciones de imagen
// 增加禁止加载图片的设置
HashMap<String, Object> prefs = new HashMap<>();
prefs.put("profile.default_content_settings", 2);
chromeOptions.setExperimentalOption("prefs", prefs);
chromeOptions.addArguments("blink-settings=imagesEnabled=false");//禁用图片
2.8 Cargar dirección de blogger
String baseUrl = "https://blog.csdn.net/s445320?type=blog";
2.9 Cargar lista de artículos
//定位到文章列表
WebElement mainSelectE = driver.findElement(By.cssSelector("div.mainContent"));
2.10 Cargar la página siguiente
Simule la barra de desplazamiento del navegador para desplegar y cargar la siguiente página de datos
//加载下一页
JavascriptExecutor jsDriver = (JavascriptExecutor) driver;//将java中的driver强制转型为JS类型
jsDriver.executeScript("window.scrollTo(0, 50)");
jsDriver.executeScript("window.scrollTo(0, document.body.scrollHeight-20)");
SeleniumUtil.sleep(500);
jsDriver.executeScript("window.scrollTo(0, document.body.scrollHeight +1)");
SeleniumUtil.sleep(2000);
2.11 Configurar para cargar 100 piezas de datos
// 获取Top100的数量
int topNum = 100;
//如果加载的数据超过或等于 要求的最大长度,返回现在已加载的数据
if( webElements.size() >= topNum ) {
for(WebElement element : webElements ){
System.out.println( element.getAttribute("href") );
blogUrlList.add(element.getAttribute("href"));
}
log.info("文章已读取 {} 条,最大限制 {} 条!" , webElements.size() , topNum);
break;
}
2.12 Optimizado el cambio frecuente del navegador Chrome
optimización 1
Para los artículos Top40 del capítulo anterior, se realizó una optimización simple: al consultar el puntaje de calidad del blog, se controló el cambio frecuente del navegador Chrome y se evitó la carga repetida del controlador Chrome y la apertura del navegador Chrome.
optimización 2
Cargue y consulte la subpágina de calidad del blog por primera vez, y luego solo necesita cambiar la dirección del enlace de la publicación del blog para obtener los datos.
/**
* 获取质量数据
* @throws IOException
*/
CsdnBlogInfo csdnQcBySelenium(String blogUrl , WebDriver driver , boolean isFirst) {
log.info("csdnQcBySelenium start!");
CsdnBlogInfo csdnBlogInfo = new CsdnBlogInfo();
//第一次时加载查询质量分页面
if( isFirst ) {
driver.get("https://www.csdn.net/qc");
SeleniumUtil.sleep(500);
}
2.13 Resultados
00:44:50.693 [main] INFO com.kelvin.spiderx.service.CsdnQcService - csdnQcBySelenium start!
00:45:03.151 [main] INFO com.kelvin.spiderx.service.CsdnQcService - 文章已读取 100 条,最大限制 100 条!
00:45:03.151 [main] INFO com.kelvin.spiderx.service.CsdnQcService - blogUrlList size:100
00:45:03.294 [main] INFO com.kelvin.spiderx.service.CsdnQcService - blogUrlList:
[{
"title":"[刷题] 删除有序数组中的重复项","posttime":"- 青花锁 · 2023-06-25 12:49:42 -","score":"82","remark":"文章质量良好"},{
"title":"[Selenium] 通过Java+Selenium查询某个博主的Top40文章质量分","posttime":"- 青花锁 · 2023-06-25 01:22:55 -","score":"87","remark":"文章质量良好"},{
"title":"[Selenium] 通过Java+Selenium查询文章质量分","posttime":"- 青花锁 · 2023-06-23 08:42:36 -","score":"86","remark":"文章质量良好"},{
"title":"【并发知识点】CAS的实现原理及应用","posttime":"- 青花锁 · 2023-06-22 11:55:48 -","score":"90","remark":"文章质量良好"},{
"title":"【并发知识点】AQS的实现原理及应用","posttime":"- 青花锁 · 2023-06-22 11:35:53 -","score":"90","remark":"文章质量良好"},{
"title":"简单介绍html/javascript、ajax应用","posttime":"- 青花锁 · 2023-06-22 10:18:01 -","score":"92","remark":"文章质量良好"},{
"title":"[设计模式] OOP六大原则","posttime":"- 青花锁 · 2023-06-22 01:24:19 -","score":"89","remark":"文章质量良好"},{
"title":"[Web前端] Servlet及应用","posttime":"- 青花锁 · 2023-06-22 01:07:56 -","score":"91","remark":"文章质量良好"},{
"title":"【在线商城系统】数据来源-爬虫篇","posttime":"- 青花锁 · 2023-06-22 00:48:46 -","score":"87","remark":"文章质量良好"},{
"title":"《项目实战》构建SpringCloud alibaba项目(三、构建服务方子工程store-user-service)","posttime":"- 青花锁 · 2023-06-21 18:20:46 -","score":"86","remark":"文章质量良好"},{
"title":"《项目实战》构建SpringCloud alibaba项目(二、构建微服务鉴权子工程store-authority-service)","posttime":"- 青花锁 · 2023-06-19 17:24:53 -","score":"86","remark":"文章质量良好"},{
"title":"《项目实战》使用JDBC手写分库","posttime":"- 青花锁 · 2023-06-16 17:56:03 -","score":"88","remark":"文章质量良好"},{
"title":"《项目实战》构建SpringCloud alibaba项目(一、构建父工程、公共库、网关))","posttime":"- 青花锁 · 2023-06-15 20:41:46 -","score":"92","remark":"文章质量良好"},{
"title":"《项目实战》 Jenkins 与 CICD、发布脚本","posttime":"- 青花锁 · 2023-06-13 15:53:46 -","score":"90","remark":"文章质量良好"},{
"title":"《微服务实战》 第三十二章 微服务链路跟踪-sleuth zipkin","posttime":"- 青花锁 · 2023-06-11 18:41:09 -","score":"90","remark":"文章质量良好"},{
"title":"《微服务实战》 第三十一章 ShardingSphere - ShardingSphere-JDBC","posttime":"- 青花锁 · 2023-06-11 18:25:34 -","score":"80","remark":"文章质量良好"},{
"title":"《微服务实战》 第三十章 分布式事务框架seata TCC模式","posttime":"- 青花锁 · 2023-06-11 10:38:21 -","score":"89","remark":"文章质量良好"},{
"title":"《微服务实战》 第二十九章 分布式事务框架seata AT模式","posttime":"- 青花锁 · 2023-06-11 10:23:44 -","score":"92","remark":"文章质量良好"},{
"title":"《微服务实战》 第二十八章 分布式锁框架-Redisson","posttime":"- 青花锁 · 2023-06-09 17:55:59 -","score":"91","remark":"文章质量良好"},{
"title":"【项目实战】一、Spring boot整合JWT、Vue案例展示用户鉴权","posttime":"- 青花锁 · 2023-06-09 09:06:43 -","score":"92","remark":"文章质量良好"},{
"title":"《微服务实战》 第二十七章 CAS","posttime":"- 青花锁 · 2023-05-30 16:26:30 -","score":"87","remark":"文章质量良好"},{
"title":"《微服务实战》 第二十六章 Java锁的分类","posttime":"- 青花锁 · 2023-05-29 17:28:47 -","score":"91","remark":"文章质量良好"},{
"title":"《微服务实战》 第二十五章 Java多线程安全与锁","posttime":"- 青花锁 · 2023-05-29 16:07:53 -","score":"91","remark":"文章质量良好"}.....]
00:45:03.296 [main] INFO com.kelvin.spiderx.service.CsdnQcService - 此博主有文章,开始解析文章质量分!
00:45:03.296 [main] INFO com.kelvin.spiderx.service.CsdnQcService - csdnQcBySelenium start!
---------- 省略解析过程
此博主质量分如下:
00:50:40.699 [main] INFO com.kelvin.spiderx.service.CsdnQcService - {
"title":"[刷题] 删除有序数组中的重复项","posttime":"- 青花锁 · 2023-06-25 12:49:42 -","score":"82","remark":"文章质量良好"},{
"title":"[Selenium] 通过Java+Selenium查询某个博主的Top40文章质量分","posttime":"- 青花锁 · 2023-06-25 01:22:55 -","score":"87","remark":"文章质量良好"},{
"title":"[Selenium] 通过Java+Selenium查询文章质量分","posttime":"- 青花锁 · 2023-06-23 08:42:36 -","score":"86","remark":"文章质量良好"},{
"title":"【并发知识点】CAS的实现原理及应用","posttime":"- 青花锁 · 2023-06-22 11:55:48 -","score":"90","remark":"文章质量良好"},{
"title":"【并发知识点】AQS的实现原理及应用","posttime":"- 青花锁 · 2023-06-22 11:35:53 -","score":"90","remark":"文章质量良好"},{
"title":"简单介绍html/javascript、ajax应用","posttime":"- 青花锁 · 2023-06-22 10:18:01 -","score":"92","remark":"文章质量良好"},{
"title":"[设计模式] OOP六大原则","posttime":"- 青花锁 · 2023-06-22 01:24:19 -","score":"89","remark":"文章质量良好"},{
"title":"[Web前端] Servlet及应用","posttime":"- 青花锁 · 2023-06-22 01:07:56 -","score":"91","remark":"文章质量良好"}....]
00:50:40.693 [main] INFO com.kelvin.spiderx.service.CsdnQcService - csdnQcBySelenium end!
3. Puntuación de calidad del artículo de consulta circular
Consultar el puntaje de calidad del artículo a través de Java+Selenium Consultar
el puntaje de calidad del artículo se puede encontrar en el artículo anterior.En el capítulo anterior, se optimizaron el valor de retorno y la prohibición de carga de imágenes. En este capítulo, el controlador está optimizado, varias páginas de consulta comparten un controlador y, al ingresar a la etapa de calidad de la consulta, solo se carga la página por primera vez.
Observaciones: En la etapa posterior, para el puntaje de calidad de la consulta, en caso de concurrencia, se puede considerar la tecnología de agrupación de controladores y 100 artículos se dividen en N secciones, que se asignan a trabajos por separado para optimizar el rendimiento.
4. Código
package com.kelvin.spiderx.service;
import com.google.gson.Gson;
import com.kelvin.spiderx.util.SeleniumUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/***
* @title CsdnQcService
* @desctption CSDN查询质量分
* @author LTF
* @create 2023/6/21 23:02
**/
@Slf4j
public class CsdnQcService {
@Data
class CsdnBlogInfo {
private String title;
private String posttime;
private String score;
private String remark;
}
/**
* 获取质量数据
* @throws IOException
*/
CsdnBlogInfo csdnQcBySelenium(String blogUrl , WebDriver driver , boolean isFirst) {
log.info("csdnQcBySelenium start!");
CsdnBlogInfo csdnBlogInfo = new CsdnBlogInfo();
if( isFirst ) {
driver.get("https://www.csdn.net/qc");
SeleniumUtil.sleep(500);
}
//定位到输入框
WebElement inputSelectE = driver.findElement(By.cssSelector("input.el-input__inner"));
//输入文字地址
inputSelectE.sendKeys(blogUrl);
SeleniumUtil.sleep(100);
//定位查询按钮
WebElement qcSelectE = driver.findElement(By.cssSelector("div.trends-input-box-btn"));
//点击查询按钮
qcSelectE.click();
SeleniumUtil.sleep(1000);
//获取右边区域 -- 文章质量分结果区域
WebElement mainSelectE = driver.findElement(By.cssSelector("div.csdn-body-right"));
//转化为Jsoup文档处理
Document doc = Jsoup.parse( mainSelectE.getAttribute("outerHTML") );
//获取文章标题
String title = doc.select("span.title").text();
if(!StringUtils.isEmpty(title)) {
csdnBlogInfo.setTitle(title);
}
//获取作者和发布时间
String posttime = doc.select("span.name").text();
if(!StringUtils.isEmpty(posttime)) {
csdnBlogInfo.setPosttime(posttime);
}
//获取质量分
String score = doc.select("p.img").text();
if(!StringUtils.isEmpty(score)) {
csdnBlogInfo.setScore(score);
}
//获取博文质量分建议
String remark = doc.select("p.desc").text();
if(!StringUtils.isEmpty(remark)) {
csdnBlogInfo.setRemark(remark);
}
//打印结果
log.info("文章标题:{} , 作者和发布时间:{} , 质量分:{} , 博文建议:{}" , title , posttime , score , remark );
// driver.quit();
log.info("csdnQcBySelenium end!");
return csdnBlogInfo;
}
/**
* 查询指定博主的文章质量分
*/
void allBlogQcDataBySelenium() {
String baseUrl = "https://blog.csdn.net/s445320?type=blog";
System.setProperty("webdriver.chrome.driver", SeleniumUtil.CHROMEDRIVERPATH );// chromedriver localPath
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.addArguments("--remote-allow-origins=*");
chromeOptions.addArguments("–no-sandbox"); //--start-maximized
// 增加禁止加载图片的设置
HashMap<String, Object> prefs = new HashMap<>();
prefs.put("profile.default_content_settings", 2);
chromeOptions.setExperimentalOption("prefs", prefs);
chromeOptions.addArguments("blink-settings=imagesEnabled=false");//禁用图片
WebDriver driver = new ChromeDriver(chromeOptions);
driver.get(baseUrl);
SeleniumUtil.sleep(200);
//定位到文章列表
WebElement mainSelectE = driver.findElement(By.cssSelector("div.mainContent"));
boolean isEnd = false;
// 获取Top40的数量
int topNum = 100;
// 上一次读取的文章数
int prePoint = 0;
List<String> blogUrlList = new ArrayList<>();
List<WebElement> webElements = null;
while ( isEnd == false ) {
JavascriptExecutor jsDriver = (JavascriptExecutor) driver;//将java中的driver强制转型为JS类型
jsDriver.executeScript("window.scrollTo(0, 50)");
jsDriver.executeScript("window.scrollTo(0, document.body.scrollHeight-20)");
SeleniumUtil.sleep(500);
jsDriver.executeScript("window.scrollTo(0, document.body.scrollHeight +1)");
SeleniumUtil.sleep(2000);
webElements = mainSelectE.findElements(By.cssSelector("article.blog-list-box>a"));
// 如果上一次的文章数
// 等于 当前页面的文章数:文章已全部读取完
// 否则,继续加载下一页
if( webElements.size() == prePoint){
for(WebElement element : webElements ){
System.out.println( element.getAttribute("href") );
blogUrlList.add(element.getAttribute("href"));
}
log.info("文章已全部读取完");
break;
} else {
prePoint = webElements.size();
}
//如果加载的数据超过或等于 要求的最大长度,返回现在已加载的数据
if( webElements.size() >= topNum ) {
for(WebElement element : webElements ){
System.out.println( element.getAttribute("href") );
blogUrlList.add(element.getAttribute("href"));
}
log.info("文章已读取 {} 条,最大限制 {} 条!" , webElements.size() , topNum);
break;
}
}
log.info("blogUrlList size:{}" , blogUrlList.size());
log.info("blogUrlList:{}" , new Gson().toJson(blogUrlList) );
List<CsdnBlogInfo> csdnBlogInfoList = null;
if(CollectionUtils.isEmpty(blogUrlList)) {
log.info("此博主没有发表文章!");
} else {
log.info("此博主有文章,开始解析文章质量分!");
csdnBlogInfoList = new ArrayList<>();
int num = 0;
for (String blogUrl : blogUrlList) {
try{
CsdnBlogInfo csdnBlogInfo = this.csdnQcBySelenium(blogUrl , driver , num <= 0 );
if( null != csdnBlogInfo ) {
csdnBlogInfoList.add(csdnBlogInfo);
}
num ++;
} catch (Exception e) {
log.info("解析文章质量分失败,文章:{}" , blogUrl);
}
}
if(CollectionUtils.isEmpty(csdnBlogInfoList)) {
log.info("解析文章质量分失败!");
} else {
log.info("此博主质量分如下:");
log.info(new Gson().toJson(csdnBlogInfoList));
}
}
driver.quit();
log.info("读取数据完毕!the end!");
}
public static void main(String[] args) {
CsdnQcService csdnQcService = new CsdnQcService();
csdnQcService.allBlogQcDataBySelenium();
}
}
Resumir
Este es el fin de consultar el puntaje de calidad de los 100 artículos principales de un blogger a través de Java + Selenium, y todavía hay mucho espacio para la optimización, principalmente para lograr resultados.