자바 다 중 스 레 드 및 분포 식 파충류 구조 원리 분석
앞의 몇 장의 내용 은 우리 의 파충류 프로그램 이 모두 단일 라인 이다.우리 가 파충류 프로그램 을 디 버 깅 할 때 단일 라인 파충 류 는 아무런 문제 가 없 지만,우리 가 온라인 환경 에서 단일 라인 파충 류 프로그램 을 사용 하여 웹 페이지 를 채집 할 때 단일 라인 은 두 가지 치 명 적 인 문 제 를 드 러 냈 다.
4.567917.채집 효율 이 매우 느 리 고 단일 스 레 드 간 에 직렬 로 되 어 있 으 며 다음 실행 동작 은 이전 실행 이 끝나 야 실행 할 수 있 습 니 다
다 중 스 레 드 의 파충류 프로 그래 밍 은 단일 스 레 드 보다 훨씬 복잡 하지만 다른 업무 가 높 고 데이터 안전 을 확보 해 야 하 는 것 과 달리 다 중 스 레 드 파충류 가 데이터 안전 에 있어 요구 가 그리 높 지 않다.모든 페이지 가 하나의 입체 로 볼 수 있 기 때문이다.많은 스 레 드 파충 류 를 하려 면 반드시 두 가 지 를 잘 해 야 한다.첫 번 째 는 채집 대기 URL 유지 이다.두 번 째 는 URL 의 무 게 를 없 애 는 것 이다.다음은 우리 가 간단하게 이 두 가 지 를 이야기 하 자.
수집 할 URL 유지
다 중 스 레 드 파충류 프로그램 은 단일 스 레 드 처럼 모든 스 레 드 가 자신의 채집 대기 URL 을 혼자 유지 할 수 없습니다.만약 그렇다면 모든 스 레 드 가 수집 한 웹 페이지 는 똑 같 을 것 입 니 다.이것 은 다 중 스 레 드 채집 이 아 닙 니 다.한 페이지 를 여러 번 수집 하 는 것 입 니 다.이 를 바탕 으로 저 희 는 수집 해 야 할 URL 을 통일 적 으로 유지 해 야 합 니 다.모든 스 레 드 는 통 일 된 URL 유지보수 에서 채집 URL 을 받 고 채집 작업 을 완성 해 야 합 니 다.페이지 에서 새로운 URL 링크 를 발견 하면 통 일 된 URL 유지보수 용기 에 추가 합 니 다.다음은 URL 유지 보수 에 적합 한 몇 가지 용기 입 니 다.
URL 의 무 게 를 줄 이 는 것 도 다 중 스 레 드 채집 의 관건 적 인 단계 입 니 다.무 게 를 줄 이지 않 으 면 중복 되 는 URL 을 대량으로 수집 할 것 입 니 다.그러면 우리 의 채집 효율 을 향상 시 키 지 못 합 니 다.예 를 들 어 한 페이지 의 뉴스 목록 입 니 다.우 리 는 첫 페이지 를 채집 할 때 2,3,4,5 페이지 의 링크 를 얻 을 수 있 고 두 번 째 페이지 를 채집 할 때 1,3,4 를 얻 을 수 있 습 니 다.5 페이지 의 링크 입 니 다.수집 할 URL 대기 열 에 대량의 목록 페이지 링크 가 존재 합 니 다.그러면 반복 채집 을 하거나 순환 에 들 어가 기 때문에 URL 을 다시 해 야 합 니 다.URL 무 게 를 줄 이 는 방법 은 매우 많 습 니 다.다음은 자주 사용 하 는 URL 무 게 를 줄 이 는 방법 입 니 다.
위 에서 우 리 는 주로 다 중 스 레 드 파충류 의 구조 디자인 을 알 게 되 었 습 니 다.그 다음 에 자바 다 중 스 레 드 파충 류 를 시도 해 보 겠 습 니 다.우 리 는 호랑이 뉴스 를 채집 하 는 것 을 예 로 들 어 자바 다 중 스 레 드 파충 류 를 실전 해 보 겠 습 니 다.자바 다 중 스 레 드 파충 류 는 채집 해 야 할 URL 의 유지 와 URL 을 무 겁 게 디자인 했 습 니 다.우 리 는 여기 서 시연 만 하기 때문에 JDK 에 내 장 된 용 기 를 사용 하여 완성 합 니 다.저 희 는 LinkedBlockingQueue 를 채집 대기 URL 유지보수 용기 로 사용 하고 HashSet 을 URL 로 재 활용 기 를 사용 합 니 다.다음은 자바 다 중 스 레 드 파충류 의 핵심 코드 입 니 다.자세 한 코드 는 GitHub 를 업로드 하고 주 소 는 글 끝 에 있 습 니 다.
/**
*
*/
public class ThreadCrawler implements Runnable {
//
private final AtomicLong pageCount = new AtomicLong(0);
//
public static final String URL_LIST = "https://voice.hupu.com/nba";
protected Logger logger = LoggerFactory.getLogger(getClass());
//
LinkedBlockingQueue<String> taskQueue;
//
HashSet<String> visited;
//
CountableThreadPool threadPool;
/**
*
* @param url
* @param threadNum
* @throws InterruptedException
*/
public ThreadCrawler(String url, int threadNum) throws InterruptedException {
this.taskQueue = new LinkedBlockingQueue<>();
this.threadPool = new CountableThreadPool(threadNum);
this.visited = new HashSet<>();
//
this.taskQueue.put(url);
}
@Override
public void run() {
logger.info("Spider started!");
while (!Thread.currentThread().isInterrupted()) {
// URL
final String request = taskQueue.poll();
// request ,
if (request == null) {
if (threadPool.getThreadAlive() == 0) {
break;
}
} else {
//
threadPool.execute(new Runnable() {
@Override
public void run() {
try {
processRequest(request);
} catch (Exception e) {
logger.error("process request " + request + " error", e);
} finally {
// +1
pageCount.incrementAndGet();
}
}
});
}
}
threadPool.shutdown();
logger.info("Spider closed! {} pages downloaded.", pageCount.get());
}
/**
*
* @param url
*/
protected void processRequest(String url) {
//
if (url.matches(URL_LIST)) {
// URL
processTaskQueue(url);
} else {
//
processPage(url);
}
}
/**
*
* , url
*
* @param url
*/
protected void processTaskQueue(String url) {
try {
Document doc = Jsoup.connect(url).get();
//
Elements elements = doc.select(" div.news-list > ul > li > div.list-hd > h4 > a");
elements.stream().forEach((element -> {
String request = element.attr("href");
// set ,
if (!visited.contains(request) && !taskQueue.contains(request)) {
try {
taskQueue.put(request);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}));
//
Elements list_urls = doc.select("div.voice-paging > a");
list_urls.stream().forEach((element -> {
String request = element.absUrl("href");
//
if (request.matches(URL_LIST)) {
// set ,
if (!visited.contains(request) && !taskQueue.contains(request)) {
try {
taskQueue.put(request);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
*
*
* @param url
*/
protected void processPage(String url) {
try {
Document doc = Jsoup.connect(url).get();
String title = doc.select("body > div.hp-wrap > div.voice-main > div.artical-title > h1").first().ownText();
System.out.println(Thread.currentThread().getName() + " " + new Date() + " " + title);
// url set
visited.add(url);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
new ThreadCrawler("https://voice.hupu.com/nba", 5).run();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
우 리 는 5 개의 스 레 드 로 호랑이 뉴스 목록 페이지 를 채집 하여 효 과 를 보 았 다.만약 에?이 프로그램 을 실행 하면 다음 과 같은 결 과 를 얻 을 수 있 습 니 다.다 중 스 레 드 채집 결과
결 과 를 통 해 알 수 있 듯 이 우 리 는 5 개의 스 레 드 를 시작 하여 61 페이지 를 채 집 했 습 니 다.모두 2 초 걸 렸 습 니 다.효과 가 좋다 고 할 수 있 습 니 다.우 리 는 단일 스 레 드 와 비교 해서 차이 가 얼마나 큰 지 봅 시다.우 리 는 스 레 드 수 를 1 로 설정 하고 프로그램 을 다시 시작 하여 다음 과 같은 결 과 를 얻 을 수 있 습 니 다.
단일 스 레 드 실행 결과
이 를 통 해 알 수 있 듯 이 단일 스 레 드 에서 호랑이 가 61 개의 뉴스 를 수집 하 는 데 7 초 가 걸 렸 다.시간 차 이 는 다 중 스 레 드 의 4 배 에 불과 하 다.이것 은 61 페이지 에 불과 하 다.페이지 가 많 으 면 차이 가 점점 커지 기 때문에 다 중 스 레 드 파충류 의 효율 이 매우 높다.
분산 식 파충류 구조
분포 식 파충류 구 조 는 대형 채집 프로그램 이 사용 해 야 하 는 구조 이다.일반적인 상황 에서 단기 다 중 스 레 드 를 사용 하면 업무 수 요 를 해결 할 수 있다.어쨌든 나 는 분포 식 파충류 프로젝트 의 경험 이 없 기 때문에 이 부분 은 나 도 할 말 이 없다.그러나 우 리 는 기술자 로 서 기술 보존 열 도 를 필요 로 한다.비록 사용 하지 않 지만 이해 해도 무방 하 다.나 는 많은 자 료 를 찾 아 보고 다음 과 같은 결론 을 얻 었 다.
분포 식 파충류 구 조 는 우리 의 다 중 스 레 드 파충류 구조 와 사고방식 에 있어 서 똑같다.우 리 는 다 중 스 레 드 를 바탕 으로 조금 만 개선 하면 간단 한 분포 식 파충류 구조 가 될 수 있다.분포 식 파충류 구조 에서 파충류 프로그램 은 서로 다른 기계 에 배치 되 어 있 기 때문에 우리 가 수집 해 야 할 URL 과 수집 한 URL 은 파충류 프로그램 기계 의 메모리 에 저장 할 수 없다.우 리 는 이 를 특정한 기계 에 통일 적 으로 유지 해 야 한다.예 를 들 어 Redis 나 MongoDB 에 저장 하고 모든 기 계 는 이 위 에서 채집 링크 를 가 져 와 야 한다.링크 드 BlockingQueue 와 같은 메모리 대기 열 에서 링크 를 찾 는 것 이 아니 라 간단 한 분포 식 파충류 구조 가 나 타 났 습 니 다.물론 이 안 에는 많은 세부 적 인 문제 가 있 을 것 입 니 다.저 는 분포 식 구조 경험 이 없 기 때문에 저도 말 할 수 없습니다.관심 이 있다 면 교 류 를 환영 합 니 다.
소스 코드:소스 코드
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.