기본 아이디어
원산지 : Master : Wikipedia (예 : 항공 모함 (Key) 페이지와 같은 특정 범주에서 시작하여 링크의 제목 속성에서 열쇠 (항공 모함)가 포함 된 모든 대상을 찾아 큐에 추가하여 크롤링 될 대기열에 추가합니다.이 방법으로는 페이지의 코드와 사진을 잡고 웹 페이지의 키와 관련된 모든 웹 페이지의 주소를 얻는 동안, 개상 및 개조물의 주소를 얻습니다. 이 작업을 완료하는 폭.
아이디어 2 (원산지 : 고양이) : 분류 별 크롤링. Wikipedia에서 카테고리는 카테고리로 시작합니다. Wikipedia는 좋은 문서 구조를 가지고 있으므로 모든 카테고리부터 시작하기 쉽고 항상 아래의 모든 카테고리를 크롤링 할 수 있습니다. 이 알고리즘은 분류 페이지의 하위 분류를 추출하고 아래의 모든 페이지를 병렬로 가져옵니다. 빠르고 분류 구조를 저장할 수 있지만 실제로 많은 중복 페이지가 있지만 이후에는 스크립트를 작성하여 쉽게 처리 할 수 있습니다.
도서관 선택
나는 JSDOM을 사용하기 시작했습니다. 나는 그것이 강력하다고 느꼈지만, 그것은 또한 상당히 "무겁다"고 느꼈다. 가장 심각한 것은 설명 문서가 충분하지 않다는 것입니다. 나는 그것의 장점 만 언급했지만 포괄적 인 설명은 없었습니다. 따라서 Cheerio로 변경하면 가벼우 며 비교적 완전한 기능이 있습니다. 적어도 당신은 한 눈에 포괄적 인 개념을 가질 수 있습니다. 사실, 그것을 한 후에, 나는 도서관이 전혀 필요하지 않다는 것을 깨달았으며 정기적 인 표현으로 모든 것을 할 수 있습니다! 방금 도서관에서 약간의 규칙 성을 썼습니다.
핵심 요점
글로벌 변수 설정 :
var regkey = [ '항공기 캐리어', '항공 모함', '항공 모함']; // 키워드가 링크에 포함되면 대상 var allkeys = []; // 링크의 제목은 또한 페이지 식별자이기도합니다. Var Keys의 반복 크롤링을 피하십시오 = [ '범주 :%e8%88%AA%a7%a9%ba%e6%a6%8d%e8%88%b0']; // 대기열을 기다리고 페이지를 시작합니다
이미지 다운로드
요청 라이브러리의 스트리밍 작업을 사용하여 각 다운로드 작업을 형성하여 폐쇄하십시오. 비동기 작업의 가능한 부작용에주의하십시오. 또한 이미지 이름을 재설정해야합니다. 처음에는 원래 이름을 가져갔습니다. 어떤 이유로, 일부 이미지는 분명히 존재하지만 표시 할 수는 없습니다. SRCSET 속성을 지워야합니다. 그렇지 않으면 원래 표면을 표시 할 수 없습니다.
$ = cheer.load (downhtml); var rshtml = $ .html (); var imgs = $ ( '#bodyContent .Image'); // 사진은 (IMG in IMGS) {if (IMGS [IMG] .attribs === 'attribs'|| imgs [img] .attribs.href === 'undefined') {계속;} // 링크 아래 이미지가 존재하지 않는다. imgs [img] .Children [0] .attribs.src; // 이미지 주소 var dirs = picurl.split ( '.'); var filename = basedir+uuid.v1 ()+'.'+dirs [dir.length -1]; // 요청 이름 바꾸기 ( "https :"+picurl) .pipe (fs.createwritestream ( 'pages/'+filename)); // 다운로드 rshtml = rshtml.replace (picurl, filename); // 로컬 경로 교체 // console.log (picurl); }}폭 넓은 우선 순위 트래버스
처음에는 비동기식의 개념을 완전히 이해하지 못했고 루프에서 그것을했습니다. 나는 약속을 사용하여 이미 동기화로 변환되었다고 생각했지만 실제로 약속을 위해 양도 된 작업이 질서 정연하게 수행 될 것이며 이러한 작업은 다른 운영으로 주문할 수 없도록 보장합니다! 예를 들어 다음 코드가 올바르지 않습니다.
var keys = [ '항공기 캐리어']; var 키 = keys.shift (); while (key) {data.get ({url : encodeuri (key), qs : null}). 그런 다음 (function (downhtml) {... keys.push (key); // (1)}}); key = keys.shift (); // (2)}위의 작업은 정상이지만 실제로 (2)는 (1) 사이에 실행됩니다! 무엇을해야합니까?
이 문제를 해결하기 위해 재귀를 사용했습니다. 다음 예제 코드 :
var key = keys.shift (); (함수 donext (key) {data.get ({url : key, qs : null}). 그런 다음 (function (downhtml) {... keys.push (href); ... key = keys.shift (); if (key) {donext (key); else {console.log (crawl Wasking이 smoothly) })})(열쇠);정기적 인 청소
정규 표현식을 사용하여 쓸모없는 페이지 코드를 청소하십시오. 처리 할 패턴이 많이 있으므로 균일하게 처리하기 위해 루프를 작성했습니다.
var regs = [/<link rel =/"스타일 시트/"href =/"? [^/"]*/">/g,/<cript> regs.foreach (function (rs) {var mactches = rshtml.match (rs); for (var i = 0; i <mactches.length; i ++) {rshtml = rshtml.replace (mactches [i], mactches [i]. indexof ( 'stylesheet')-1 link? href = "wiki '+(i+1)+'. css" ':' ');실행 효과
Wiki Chinese에 FQ가 필요합니다. 나는 그것을 시도하고 항공 모함 분류를 잡았다. 작업 중에 약 300 개의 관련 링크를 발견했습니다 (분류 페이지 포함. 유효한 링크 만 가져와 다운로드하지 않았습니다). 마지막으로 209를 올바르게 다운로드했습니다. 수동으로 일부 오류 링크를 테스트 한 결과 잘못된 링크임을 발견했습니다. 그것은 항목이 아직 설정되지 않았다는 것을 보여 주었다. 전체 프로세스는 15 분도 채 걸리지 않았습니다. 압축 후, 거의 30m이었고 그 효과가 꽤 좋다고 생각했습니다.
소스 코드
https://github.com/zhoutk/wikispider
요약
어젯밤 작업을 기본적으로 완료 할 때, 아이디어 1은 비교적 정확한 콘텐츠로 페이지를 크롤링 할 수 있으며 페이지는 반복되지 않지만 크롤링 효율은 높지 않으며 분류 된 정보는 정확하게 얻을 수 없습니다. 아이디어 2는 Wikipedia에 따르면 (실제 측정, 크롤링 [군함] 총 6,000 페이지를 크롤링하는 약 50 분이 걸리며 분당 100 페이지 이상을 크롤링 할 수있는 Wikipedia에 따르면 Wikipedia에 따르면 카테고리에 로컬로 파일을 자동으로 크롤링하고 저장할 수 있습니다.
가장 큰 이익은 비동기 프로그래밍의 전반적인 프로세스 제어에 대한 깊은 이해입니다.