작고 유연한 Java 다중 스레드 파충류 프레임워크(Aipa)

7611 단어
1. 소개
Aipa는 작고 유연하며 확장성이 높은 다중 스레드 파충류 프레임이다.
Aipa는 현재 가장 간단한 HTML 파서 Jsoup에 의존합니다.
Aipa는 사용자가 사이트 주소 집합을 제공하기만 하면 다중 스레드에서 자동으로 추출하고 일부 이상을 처리할 수 있다.
2.Maven
직접 도입

    cn.yueshutong
    AiPa
    1.0.0.RELEASE

3. 어떻게 사용하는가
먼저 다음 간단하고 완전한 예시 프로그램을 살펴보자.
필수 인터페이스
public class MyAiPaWorker implements AiPaWorker {

    @Override
    public String run(Document doc, AiPaUtil util) {
        //  JSOUP  HTML       div     
        //            
        //  aiPaUtil           
        return doc.title() + doc.body().text();
    }

    @Override
    public Boolean fail(String link) {
        //      
        //        
        //    
        return false;
    }
}

main 방법
    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ExecutionException, InterruptedException {
        //      
        List linkList = new ArrayList<>();
        linkList.add("http://jb39.com/jibing/FeiQiZhong265988.htm");
        linkList.add("http://jb39.com/jibing/XiaoErGuoDu262953.htm");
        linkList.add("http://jb39.com/jibing/XinShengErShiFei250995.htm");
        linkList.add("http://jb39.com/jibing/GaoYuanFeiShuiZhong260310.htm");
        linkList.add("http://jb39.com/zhengzhuang/LuoYin337449.htm");
        //   :  AiPa  
        AiPaExecutor aiPaExecutor = AiPa.newInstance(new MyAiPaWorker()).setCharset(Charset.forName("GBK"));
        //   :    
        for (int i = 0; i < 10; i++) {
            aiPaExecutor.submit(linkList);
        }
        //   :     
        List futureList = aiPaExecutor.getFutureList();
        for (int i = 0; i < futureList.size(); i++) {
            //get()                 
            System.out.println(futureList.get(i).get());
        }
        //   :     
        aiPaExecutor.shutdown();
    }
AiPa.newInstance() 방법을 통해 새로운 Aipa 실례를 직접 만듭니다. 이 방법은 AipaWorker 인터페이스의 실현 클래스에 전송해야 합니다.
3.1 AipaWorker 커넥터
AipaWorker 인터페이스는 사용자가 반드시 실현해야 할 업무 종류입니다.
인터페이스 방법은 다음과 같습니다.
public interface AiPaWorker {
    /**
     *         HTML  ?
     * @param doc JSOUP     
     * @param util      
     * @return
     */
    T run(Document doc, AiPaUtil util);

    /**
     * run       fail  
     * @param link   
     * @return
     */
    S fail(String link);
}
run() 방법은 사용자가 직접 처리한 HTML 내용으로 Jsoup의 Document 클래스를 이용하여 분석하고 노드나 속성 등을 가져와 데이터베이스나 로컬 파일에 저장하는 것이다.업무 방법에서 URL을 다시 요청해야 하는 경우 도구 클래스 Util을 사용할 수 있습니다.fail() 방법은run() 방법에 이상이 생기거나 웹 페이지를 추출할 때 이상이 발생하여 여러 번 처리가 무효인 상황에서 들어가는 방법으로 이 방법의 매개 변수는 이번에 오류가 발생한 웹 주소이다.일반적으로 로그 기록 등의 조작을 한다.
3.2 디코딩, 최대 실패 횟수, 요청 헤더
Aipa를 통해 실례를 얻은 후에 바로 뒤에 많은 속성을 설정할 수 있다. 예를 들어 setCharset, setThreads, setMaxFailCount 등이다. 이런 속성이 무슨 뜻인지 다음에 표의 형식으로 설명한다.
메서드
설명
setThreads
작업 스레드 수, 기본 CPU 수량 +1, 당신도 CPU*2 등을 설정할 수 있습니다
setMaxFailCount
최대 실패 횟수, 즉 사이트에 오르는 이상 횟수, 다시 오르는 총 몇 번 시도, 기본 5
setCharset
웹 페이지의 인코딩, 난자 설정, 기본 UTF-8
setHeader
요청 헤더 설정, 맵 유형만 적용, 기본 null
setMethod
요청 메소드 설정, 기본 Method.GET
setTimeout
해석 요청 대기 시간, 기본 30초.
setUserAgent
요청한 UA를 설정합니다. 기본 컴퓨터 버전입니다.
위의 일반적인 상황에서는 충분히 쓸 수 있다. 만약에 이런 것에 만족하지 않고 너무 적다고 생각한다면 다음은 더욱 우수한 해결 방안을 제시한다.
3.3 사용자 정의 파충류
위의 프레젠테이션 프로그램에서 우리는 submit() 방법을 사용하여 제출 작업을 진행했다. 기본적으로 Jsoup+위의 굵지 않은 속성을 사용하여 기어오르기 때문에 일반적인 상황에서 충분히 사용할 수 있다. 만약에 하나하나의 Jsoup을 확장하는 방법이 너무 피곤하면 나는 기어오르는 방법을 사용자에게 무겁게 제공하여 사용자가 스스로 확장할 수 있도록 하고 싶은 대로 기어오르고 어떤 속성을 설정하든지 할 수 있다고 생각했다.
다음은 데모 사용을 살펴보겠습니다.
public class MyAiPaUtil extends AiPaUtil {

    @Override
    public Document getHtmlDocument(String link) throws IOException {
        //      JSOUP,          HTTP  ,       Document  
        //       Jsoup      
        Connection connection = Jsoup.connect(link).method(Connection.Method.GET);
        String body = connection.execute().charset("GBK").body();
        
        return Jsoup.parse(body);
    }

}

그런 다음 submit 메서드를 호출하여 작업을 커밋합니다. 코드 예:
aiPaExecutor.submit(linkList, MyAiPaUtil.class);

주의: 파충류 방법을 다시 쓰면 3.2마디의 비가조 속성은 모두 효력을 상실합니다.
3.3 반환값 읽기와 스레드 탱크 가져오기
다음 작업이 성공했는지 되돌아오는 값을 읽으려면, 위의 예시 순서를 보십시오.
public List getFutureList()

getFutureList () 방법은 작업이 실행된 후의 결과 집합을 되돌려줍니다. 집합의 구성원은 모두 Future 클래스입니다.Future 대상의 get () 방법을 호출하면 현재 작업이 실행될 때까지 기다렸다가 결과 값을 되돌려줍니다. 즉, 현재 라인을 막을 것입니다.이 클래스에는 get(long timeout, Time Unit unit), 대기 시간 설정 등 여러 가지 방법이 있다.
public ExecutorService getExecutor()

이 방법은 Aipa에서 현재 사용하고 있는 Executor 스레드 풀을 되돌려줍니다. 이 스레드 풀을 가져오면 스레드 풀을 사용하는 방법이 필요합니다.
3.4 웹 페이지를 찾을 때의 이상에 어떻게 대처할 것인가
웹 페이지를 파고들 때의 이상에 대해 이것은 정말 아픈 점이다.원인은 정말 많습니다. 당신의 네트워크가 안 되고, 사이트 서버의 네트워크가 안 됩니다. 인터넷에서 요청 헤더에 커넥션을close로 설정하고keep-alive를 사용하지 않는다고 합니다.이것은 내가 몇 백 메가의 데이터를 얻은 경험으로 너에게 알을 나란히 한다는 것을 알려준다.
그래서 나는 무뢰한 타법을 생각해내서 반복해서 기어올랐다.한 번 오르면 두 번, 두 번 오르면 세 번, 웹 페이지가 정상적으로 응답할 수 있다면 기본적으로 이 전략은 문제가 별로 없다.물론 만약에 정말 어떤 웹 페이지가 그렇게 독보적이라면 우리는 최대치를 설정하여 최대치를 초과한 것에 대해 기록을 포기하고 어떤 상황을 보게 할 것이다.나의 이 프레임워크에서도 이 문제를 전문적으로 처리하는 방법을 제시했다.
4. 테스트 용례
Java SE 테스트에서데이터베이스 등을 사용하지 않았기 때문에 직접 컨트롤러로 인쇄하는 것은 문제없다.
Spring Boot에 테스트 용례를 써서 데이터를 데이터베이스에 저장하고 실행해도 문제없다.
@RunWith(SpringRunner.class)
@SpringBootTest
public class InterApplicationTests {

    @Autowired
    private DemoResponse demoResponse;

    @Test
    public void context() throws ExecutionException, InterruptedException {
        AiPaExecutor executor = AiPa.newInstance(new AiPaWorker() {
            @Override
            public Boolean run(Document document, AiPaUtil util) {
                String title = document.title();
                demoResponse.save(new DemoEntity(title));
                return true;
            }

            @Override
            public Boolean fail(String s) {
                demoResponse.save(new DemoEntity(s));
                return false;
            }
        }).setCharset(Charset.forName("GBK"));

        List linkList = new ArrayList<>();
        linkList.add("http://jb39.com/jibing/FeiQiZhong265988.htm");
        linkList.add("http://jb39.com/jibing/XiaoErGuoDu262953.htm");
        linkList.add("http://jb39.com/jibing/XinShengErShiFei250995.htm");
        linkList.add("http://jb39.com/jibing/GaoYuanFeiShuiZhong260310.htm");
        linkList.add("http://jb39.com/zhengzhuang/LuoYin337449.htm");
        executor.submit(linkList);

        List list = executor.getFutureList();
        for (int i = 0; i < list.size(); i++) {
            //get()                 
            System.out.println(list.get(i).get());
        }
        executor.shutdown();
    }

}

실행 결과:
Hibernate: insert into demo (title) values (?)
Hibernate: insert into demo (title) values (?)
Hibernate: insert into demo (title) values (?)
Hibernate: insert into demo (title) values (?)
Hibernate: insert into demo (title) values (?)

5. 작성자 정보
작가의 수준이 제한되어 있기 때문에 틀에 반드시 약간의 빈틈이나 부족이 존재할 것이니, 전문가, 어른들이 비판을 제기하여 바로잡아 주시기 바랍니다.
내 블로그:https://yueshutong.cnblogs.com/
Github:https://github.com/yueshutong/AIPa
Giree:https://gitee.com/zyzpp/AIPa
AC QQ: 781927207

좋은 웹페이지 즐겨찾기