Idéias básicas
Origem: Mestre: A partir de uma determinada categoria de Wikipedia (como a página do porta -aviões (Key), descubra todos os alvos que contêm a chave (porta -aviões) no atributo de título do link e adicione -os à fila para serem abalados. Traversal da amplitude da classe para concluir esta tarefa.
Ideia 2 (Origem: CAT): Rastrear por classificação. Observe que na Wikipedia, as categorias começam com a categoria:. Como a Wikipedia possui uma boa estrutura de documentos, é fácil começar com qualquer categoria e sempre rasteje todas as categorias abaixo dela. Este algoritmo extrai subcategorizações para páginas de classificação e pega todas as páginas abaixo dele em paralelo. É rápido e pode salvar a estrutura de classificação, mas na verdade existem muitas páginas duplicadas, mas isso pode ser facilmente processado escrevendo um script no estágio posterior.
Seleção da biblioteca
Comecei a querer usar o JSDOM. Embora eu sentisse que era poderoso, também era bastante "pesado". O mais sério foi que o documento de explicação não era bom o suficiente. Eu mencionei apenas suas vantagens, mas não tinha uma explicação abrangente. Portanto, se você mudar para Cheerio, é leve e tem funções relativamente completas. Pelo menos você pode ter um conceito abrangente rapidamente. De fato, depois de fazê -lo, percebi que não há necessidade de bibliotecas e você pode fazer tudo com expressões regulares! Acabei de escrever um pouco de regularidade na biblioteca.
Pontos -chave
Configurações de variáveis globais:
var regkey = ['transportador de aeronaves', 'transportador de aeronaves', 'transportador de aeronave']; // Se as palavras -chave estiverem incluídas no link, é o destino var allkeys = []; // O título do link também é o identificador de página, evitando rastreamento repetido de var chaves = ['categoria:%E8%88%aa%e7%a9%ba%e6%AF%8d%E8%88%B0']; // esperando pela fila, página inicial
Download da imagem
Use a operação de streaming da biblioteca de solicitações para fazer com que cada operação de download seja um fechamento. Preste atenção aos possíveis efeitos colaterais das operações assíncronas. Além disso, o nome da imagem precisa ser redefinido. No começo, peguei o nome original. Por algumas razões, algumas imagens existem claramente, mas não podem ser exibidas; e o atributo srcset deve ser limpo, caso contrário, a superfície original não pode ser exibida.
$ = Cheer.load (Downhtml); var rshtml = $ .html (); var iMgs = $ ('#BodyContent .image'); // As imagens são modificadas por esse estilo para (img em imgs) {if (typeof imgs [img] .attribs === 'indefinido' || tipo de imgs [img] .atrribs.href === 'indefinido') {continuação; imgs [img] .Children [0] .Attribs.src; // o endereço da imagem var dir var filename = baseado+uuid.v1 ()+'.'+dirs [dir.length -1]; // renomear solicitação ("https:"+picurl) .pipe (fs.createwritestream ('páginas/'+nome do arquivo)); // download rshtml = rshtml.replace (picurl, nome do arquivo); // substitua o caminho local // console.log (picurl); }}Arraversal da amplitude da prioridade
No começo, eu não entendi completamente o conceito de assíncrono e o fiz em um loop. Eu pensei que o uso da promessa já havia sido convertido em sincronização, mas, de fato, apenas garante que as operações entregues para prometer sejam realizadas de maneira ordenada, e essas operações não podem ser ordenadas com outras operações! Por exemplo, o código a seguir está incorreto.
var keys = ['portador de aeronave']; var key = keys.shift (); while (key) {data.get ({url: codeuri (key), qs: null}). Então (function (downhtml) {... keys.push (key); // (1)}}); keys = keys.shift; // (2)}A operação acima é normal, mas de fato (2) será executada entre (1)! O que fazer?
Eu usei a recursão para resolver esse problema. O código de exemplo a seguir:
var key = keys.shift (); (function donext (key) {data.get ({url: key, qs: null}). Então (function (downhtml) {... keys.push (href); theys; })})(chave);Limpeza regular
Use expressões regulares para limpar o código de página inútil, porque existem muitos padrões a serem processados, então escrevi um loop para processá -lo uniformemente.
var regs = [/<link rel =/"Stylesheet/" href =/"? [^/"]*/">/g,/<sCript>? [^<]*<// script>/g,/<style>? [^<]*<// style>/g,/<a? reg.ForEach (function (rs) {var mactches = rshtml.match (rs); para (var i = 0; i <mactches.length; i ++) {rshtml = rshtml.replace (mactches [i], mactches [i] .indexof ('estilleseet)'> href = "wiki '+(i+1)+'. css" ':' ');Efeito de corrida
Eu preciso de FQ no chinês wiki. Eu tentei e peguei a classificação do porta -aviões. Durante a operação, encontrei cerca de 300 links relacionados (incluindo páginas de classificação. Peguei apenas links válidos e não os baixei). Finalmente, baixei 209 corretamente. Eu testei manualmente alguns links de erro e descobri que eles eram links inválidos. Ele mostrou que a entrada ainda não havia sido estabelecida. Todo o processo levou mais de quinze minutos. Após a compressão, eram quase trinta meses e sentiu que o efeito era muito bom.
código -fonte
https://github.com/zhoutk/wikispider
resumo
Quando basicamente concluí a tarefa na noite passada, a Idea 1 pode rastejar páginas com conteúdo relativamente preciso e as páginas não são repetidas, mas a eficiência de rastejamento não é alta e as informações classificadas não podem ser obtidas com precisão; A Idea 2 pode rastrear e armazenar automaticamente arquivos localmente em categorias de acordo com a Wikipedia, que é altamente eficiente (medição real, rastejamento [navio de guerra] e rastejando quase 6.000 páginas no total, que leva cerca de 50 minutos e mais de 100 páginas podem ser rastejadas por minuto) e podem salvar com precisão informações classificadas.
O maior ganho é uma profunda compreensão do controle geral do processo da programação assíncrona.