需求 

  • 这里讲的是nexus3做为maven私服服务器,下载某个仓库下的所有jar包(带文件夹,就是与maven本地仓库一样的结构),以代理仓库为例:下载代理仓库下所有的jar包

思路

  1. 我们平时用到的开源jar包都会在代理仓库缓存一份,直接找到代理仓库的文件夹,很可惜没找到。
  2. 找到所有pom.xml文件的dependency引用,然后利用maven下载到本地,此时代理仓库已经jar包了,下载不会太慢。下面针对这个思路进行简单描述:使用java语言,利用jsoup解析页面获取想要的内容(算不算爬虫呢)

实现

  1. 利用jsoup解析页面,解析第一页就是:ip:port/service/rest/repository/browse/代理仓库名/,这个页面好解析,好操作,点击文件夹进入下一级目录页面恰好就是原来url地址加上文件夹的名字,直到最后一层漏出xxx.pomxxx.jar,点击xxx.pom进入页面,获取页面指定节点的内容,拼凑成dependency引用结构,就是我们想要的。
  2. 找到要解析的页面:
    1. 进入nexus3首页
    2. 进入代理仓库页面:此页面也不错,但是不好解析,解析路径获取不到想要的内容
    3. 点击HTML View进入文件列表页(列出的就是该仓库所有的jar包,当然找到jar包得一层一层进入)
    4. 直到最后一层,找到xxx.pom,此时链接地址为:ip:port/service/rest/repository/browse/test-proxy/antlr/antlr/2.7.2/
    5. 点击xxx.pom,注意此时链接地址结构改变了,变成:ip:port/repository/test-proxy/antlr/antlr/2.7.2/antlr-2.7.2.pom,与之前变化。此时页面有我们想要的东西:project子节点groupId,artifactId,version,这些恰好是dependency引用三点定位需要的内容。有些页面比较乱,project会有parent子节点,groupId和version节点可能会在parent子节点里
    6. 将我们取得的内容按照dependency引用的规则拼接字符串就可以:
      <dependency><groupId>antlr</groupId><artifactId>antlr</artifactId><version>2.7.2</version></dependency>

代码(使用Jsoup解析页面)

package com.gw.safe.utils;


import org.apache.poi.util.DocumentHelper;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.InputSource;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.io.StringReader;
import java.io.StringWriter;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * Test
 *
 * @author shuai
 * @date 2019/8/12
 */

public class Test2 {

    public static final Logger log = LoggerFactory.getLogger(Test2.class);

    public static void main(String[] args) throws Exception {
        /**
         * 获取dependencyList
         */
        List<String> dependencyList = getDependencyList("http://ip:port/service/rest/repository/browse/仓库名/", "http://ip:port/repository/仓库名/");
        /**
         * 美化输出pom.xml文件(文件,控制台)
         */
        create(dependencyList);
    }

    /**
     * 获取私服 dependencyList
     *
     * @param url           要解析的第一页
     * @param dependencyUrl 点击.pom文件后页面路径有所变化,变化后的路径(去掉最后一层/xxx.pom)
     * @return
     * @throws Exception
     */
    public static List<String> getDependencyList(String url, String dependencyUrl) throws Exception {
        List<String> list = new ArrayList<>();
        //静态页面链接地址
        Document doc = Jsoup.connect(url).userAgent("Mozilla").timeout(4000).get();
        if (doc != null) {
            Elements elements = doc.select("table>tbody>tr>td>a");
            if (elements != null && elements.size() > 0) {
                for (Element element : elements) {
                    String uri = element.text() + "/";
                    getDependencyList(list, url, dependencyUrl, uri);
                }
            }
        }
        return list;
    }

    /**
     * 解析第二页开始的之后数个子页(递归),直到看见xxx.pom文件认为路径已经到底了
     *
     * @param list
     * @param url
     * @param dependencyUrl
     * @param uri
     * @throws Exception
     */
    private static void getDependencyList(List<String> list, String url, String dependencyUrl, String uri) throws Exception {
        try {
            Document doc = Jsoup.connect(url + uri).userAgent("Mozilla").timeout(4000).get();
            if (doc != null && doc.hasText()) {
                Elements elements = doc.select("table>tbody>tr>td>a");
                if (elements != null && elements.size() > 0) {
                    String pomUri = null;
                    Boolean flagPom = false;
                    Boolean flagJar = false;
                    for (int i = 1; i < elements.size(); i++) {
                        //查看当前页有无xxx.pom
                        if (elements.get(i).text() != null && elements.get(i).text().endsWith(".pom")) {
                            pomUri = elements.get(i).text();
                            flagPom = true;
                        }
                        //查看当前页有无xxx.jar,没有xxx.jar
                        if (elements.get(i).text() != null && elements.get(i).text().endsWith(".jar")) {
                            flagJar = true;
                        }
                    }
                    /*
                     * 有xxx.pom说明路径解析已经到底了,如果没有xxx.jar(少量)也不必解析xxx.pom了,下载不下来。
                     * 没有xxx.pom继续路径解析
                     */
                    if (flagPom) {
                        if (flagJar) {
                            if (pomUri != null) {
                                String pomUrl = dependencyUrl + uri + pomUri;
                                String dependency = getDependency(pomUrl);
                                list.add(dependency);
                            }
                        }
                    } else {
                        for (int i = 1; i < elements.size(); i++) {
                            getDependencyList(list, url, dependencyUrl, uri + elements.get(i).text() + "/");
                        }
                    }
                }
            }
        } catch (Exception e) {
            System.out.println("无法解析:" + url + uri);
        }

    }

    /**
     * 解析xxx.pom,组装dependency字符串
     *
     * @param pomUrl
     * @return
     * @throws Exception
     */
    private static String getDependency(String pomUrl) throws Exception {

        Document pom = Jsoup.connect(pomUrl).userAgent("Mozilla").timeout(4000).get();

        /**
         * 多数情况下会在project的子节点找到dependency三点定位的属性值,version和groupId属性值可能在project子节点parent下。
         */

        Element artifactId = pom.select("project>artifactId").get(0);
        Element version = null;
        Elements versions = pom.select("project>version");
        if (versions != null && versions.size() > 0) {
            version = versions.get(0);
        } else {
            version = pom.select("project>parent>version").get(0);
        }

        Element groupId = null;
        Elements groupIds = pom.select("project>groupId");
        if (groupIds != null && groupIds.size() > 0) {
            groupId = groupIds.get(0);
        } else {
            groupId = pom.select("project>parent>groupId").get(0);
        }

        /**
         * 组装我们想要的字符串。
         */
        String dependencyFormat = "<dependency><groupId>{0}</groupId><artifactId>{1}</artifactId><version>{2}</version></dependency>";
        String dependency = MessageFormat.format(dependencyFormat, groupId.text(), artifactId.text(), version.text());
        log.info("dependency->{}", dependency);
        return dependency;
    }

    /**
     * 输出pom.xml结构(文件,控制台)
     *
     * @param dependencyList
     * @throws Exception
     */
    public static void create(List<String> dependencyList) throws Exception {

        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = documentBuilderFactory.newDocumentBuilder();
        org.w3c.dom.Document document = DocumentHelper.createDocument();

        org.w3c.dom.Element project = document.createElement("project");
        project.setAttribute("xmlns", "http://maven.apache.org/POM/4.0.0");
        project.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
        project.setAttribute("xsi:schemaLocation", "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd");


        org.w3c.dom.Element modelVersion = document.createElement("modelVersion");
        modelVersion.setTextContent("4.0.0");

        org.w3c.dom.Element dependencies = document.createElement("dependencies");

        for (String dependency : dependencyList) {
            org.w3c.dom.Document doc = builder.parse(new InputSource(new StringReader(dependency)));
            org.w3c.dom.Element element = doc.getDocumentElement();
            dependencies.appendChild(document.adoptNode(element));
        }
        project.appendChild(modelVersion);
        project.appendChild(dependencies);

        document.appendChild(project);

        /**
         * 创建转换工厂,然后将创建的document转换输出到文件中或控制台
         */
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();

        /**
         * 美化输出
         */
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty(OutputKeys.CDATA_SECTION_ELEMENTS, "yes");
        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");

        /**
         * 保存到文件
         */
        transformer.transform(new DOMSource(document), new StreamResult(new File("F:\\n-pom.xml")));

        /**
         * 将document中的信息转换为字符串输出到控制台中
         */
        StringWriter stringWriter = new StringWriter();
        transformer.transform(new DOMSource(document), new StreamResult(stringWriter));
        System.out.println(stringWriter.toString());

    }

}

jsoup依赖

<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.11.3</version>
</dependency>

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐