0から1までnodejs爬虫類の小さいプログラムを学びます.
18532 ワード
爬虫類とは
wikiはこう説明しています.
「自動化ブラウズネットワーク」というプログラムです.あるいはネットロボットです.これらはインターネット検索エンジンや他の類似サイトに広く使われ、これらのサイトのコンテンツや検索方法を取得または更新します.それらは自動的にすべてのアクセス可能なページの内容を収集して、検索エンジンのためにさらに処理することができます(ダウンロードしたページを整理することができます).ユーザーが必要な情報をより速く検索することができます.
robotsプロトコル
robots.txtはウェブサイトのルートディレクトリに保存されているASCIIコードのテキストファイルで、通常はウェブ検索エンジンのローミングマシン(ネットワーク爬虫ともいう)に教えていますが、このウェブサイトのどの内容が検索エンジンのローミングマシンによって取得されてはいけないもので、どれがローミングマシンによって取得されますか?
今簡単にrobots.txtの中のいくつかの配置規則を列挙して、大まかな印象があって、爬虫類の論理に対する理解にも役立ちます.は、すべてのロボットを許可します.User-agent:* は、特定のロボットのみを許可する.spider すべてのロボットをブロックします.Displalow:/ ロボットの特定のディレクトリへのアクセスを禁止します. … アンチ爬虫類(Anti-Stard)
一般サイトは三つの方面から反爬虫類:*ユーザーから要求されたHeaders*ユーザー行為*ウェブサイトディレクトリとデータローディング方式*
前の二つは比較的に出会いやすいです.ほとんどのサイトはこれらの角度から爬虫類を反対します.第三のいくつかのajaxのウェブサイトは採用することができて、このようにして登り取りの難度を増大しました.
Headersを通してアンチ爬虫類
多くのサイトでHeadersを検出しました.-User-Agent-Refererは、ユーザ行動を検出することによって、 同じIPで短時間で何度も同じページ にアクセスします.同じアカウントで短時間に何度も同じ動作を行います.
上記のいくつかの状況はほとんどが静止画ページに現れています.一部のウェブサイトがあります.私たちが必要とするデータはajaxを通じて入手したり、JavaScriptを通じて生成したりします. Javascript及びJQuery 簡単なnodejs基礎 httpネットワークトラッキングとURLベース インストールが必要な依存ライブラリ superagent cherio eventproxy async superagent
superagentは軽いhttp側のライブラリで、nodejsの中で非常に便利なクライアント要求代理モジュールです.私達がget、postなどのネットワーク要求をしやすいです.
チェロオ
Nodejs版のjQueryは、ウェブページからcss selectorでデータを取得するために使用されています.使い方はjqueryと同じです.
イベントプログラム
eventproxyモジュールは、これらの非同期操作が完了したかどうかを管理するために、同時にN個のhttp要求を送り、その後得られたデータを利用して後期の処理を行います.完成を要求したら、自動的にあなたが提供した処理関数を呼び出して、キャプチャしたデータをパラメータとして転送して処理しやすくなります.
async
asyncはプロセス制御キットであり、直接で強力な非同期機能を提供しています.mapLimit(arr、limit、iterator、calback)
強力な同期機能もあります.map Series(arr、iterator、calback)
爬虫類の実践
うそばかり言っていますが、始めましょう.
依存ライブラリとグローバル変数を先に定義します.
ページ上のリソースを取得するためには、cherio(node版のjQuery)を使用して、ページ上で指定されたクラスまたはidの内容を選択します.だから、まず自分がページを取得したい構造を分析して、google chromeの要素選択器を開きます.
1のプログラムをcherioに参加してurlsを取得します.
これは全部相対パスですか?腫れはどうすればいいですか?急がないでください.urlモジュールがあります.
urlsを取得するのは最初のステップだけです.ここでurlsが指すページの内容を取得します.例えば、二次ページのタイトルと最初のコメントを取得してから印刷します.
ここでは、eventproxyモジュールに参加して、指定回数非同期を優雅に制御した後、コールバック関数を実行します.
えっと、ここはoutcomeが空いていますか?何の鬼ですか?またコードを確認しました.shit非同期をコントロールしていないので、topicUrls.forEach()を実行する時、topicUrlsは空です.もちろんですか?全部ありません.神器promiseに加入して改良してみましょう.
サプライズが来ました.ページには私たちが望むタイトル、url、コメントが出ていますが、予想に合わない点があります.出力ログをよく見てください.空いている対象文字列がたくさんあります.
ページはアクセスできませんか?
私達はこの出力していないページをコピーして、ブラウザで車を返すと、ページは実際にアクセスできます.ブラウザでは一回だけお願いします.爬虫類プログラムでは、nodeの高合併特性のため、同じ時間に何度もお願いします.サーバーの負荷を超えると、サーバーが崩壊します.ですから、サーバーには一般的にアンチ爬虫法がありますが、私たちはたまたまこのような状況に遭遇しました.どうやって証明しますか?私たちはurlsが指すすべてのページを直接出力します.(tips:terminalは出力が多すぎるので、linuxコマンド_;lessを使って、出力ログのページをめくることを制御できます.)
出力をよく見ると、すぐに以下のログが見つかります.
ページは全部503です.つまりサーバーは私たちの訪問を拒否しました.
私達は私達のプログラムを改良して、asyncは登場して、プログラムの合併を制御して、そして遅延を設定します.
強迫症の患者は気持ちがいいです.
ちょっと待ってください.もう一つのポイントがあります.多くのプログラム猿オタクにとって(ここでは万字を省略します)、上の基礎があります.爬虫類とストレージを実現するのも簡単です.例えば、先ほど話した例の中の二級ページの作者の顔写真をダウンロードします.ページを分析する手順は多く説明を加えなくて、直接コードをつけます.
wikiはこう説明しています.
「自動化ブラウズネットワーク」というプログラムです.あるいはネットロボットです.これらはインターネット検索エンジンや他の類似サイトに広く使われ、これらのサイトのコンテンツや検索方法を取得または更新します.それらは自動的にすべてのアクセス可能なページの内容を収集して、検索エンジンのためにさらに処理することができます(ダウンロードしたページを整理することができます).ユーザーが必要な情報をより速く検索することができます.
robotsプロトコル
robots.txtはウェブサイトのルートディレクトリに保存されているASCIIコードのテキストファイルで、通常はウェブ検索エンジンのローミングマシン(ネットワーク爬虫ともいう)に教えていますが、このウェブサイトのどの内容が検索エンジンのローミングマシンによって取得されてはいけないもので、どれがローミングマシンによって取得されますか?
Robots.txt , , 。
はっきり言って、これは強制的に守らなければならない規定ではありません.これは君子間の協議にすぎません.君子が小人を防ぐためですが、この協議を守らないと不正競争につながるかもしれません.今簡単にrobots.txtの中のいくつかの配置規則を列挙して、大まかな印象があって、爬虫類の論理に対する理解にも役立ちます.
一般サイトは三つの方面から反爬虫類:*ユーザーから要求されたHeaders*ユーザー行為*ウェブサイトディレクトリとデータローディング方式*
前の二つは比較的に出会いやすいです.ほとんどのサイトはこれらの角度から爬虫類を反対します.第三のいくつかのajaxのウェブサイトは採用することができて、このようにして登り取りの難度を増大しました.
Headersを通してアンチ爬虫類
多くのサイトでHeadersを検出しました.-User-Agent-Referer
: Headers, User-Agent Headers ; Referer 。
ユーザー行動に基づくアンチ爬虫類 :1、 , ip, ip;2、
ダイナミックページのアンチ爬虫上記のいくつかの状況はほとんどが静止画ページに現れています.一部のウェブサイトがあります.私たちが必要とするデータはajaxを通じて入手したり、JavaScriptを通じて生成したりします.
: ajax , , json 。
予備の知識が必要です.
superagentは軽いhttp側のライブラリで、nodejsの中で非常に便利なクライアント要求代理モジュールです.私達がget、postなどのネットワーク要求をしやすいです.
チェロオ
Nodejs版のjQueryは、ウェブページからcss selectorでデータを取得するために使用されています.使い方はjqueryと同じです.
イベントプログラム
eventproxyモジュールは、これらの非同期操作が完了したかどうかを管理するために、同時にN個のhttp要求を送り、その後得られたデータを利用して後期の処理を行います.完成を要求したら、自動的にあなたが提供した処理関数を呼び出して、キャプチャしたデータをパラメータとして転送して処理しやすくなります.
async
asyncはプロセス制御キットであり、直接で強力な非同期機能を提供しています.mapLimit(arr、limit、iterator、calback)
強力な同期機能もあります.map Series(arr、iterator、calback)
爬虫類の実践
うそばかり言っていますが、始めましょう.
依存ライブラリとグローバル変数を先に定義します.
// node
const path = require('path')
const url = require('url');
const fs = require('fs')
// npm
const superagent = require('superagent');
const cheerio = require('cheerio');
const eventproxy = require('eventproxy');
const async = require('async');
const mkdir = require('mkdirp')
// URL
var targetUrl = 'https://cnodejs.org/';
//-------- 1 ----------
//
superagent.get(targetUrl)
.end(function(err, res){
console.log(res);
})
三行コード~、確かに爬虫類プログラムです.画面情報をterminalに出力します.ページ上のリソースを取得するためには、cherio(node版のjQuery)を使用して、ページ上で指定されたクラスまたはidの内容を選択します.だから、まず自分がページを取得したい構造を分析して、google chromeの要素選択器を開きます.
1のプログラムをcherioに参加してurlsを取得します.
// -------- 2 ----------
// cheerio
superagent.get(targetUrl)
.end(function(err, res){
var $ = cheerio.load(res.text);
$('#topic_list .topic_title').each(function(index, element){
var href = $(element).attr('href');
console.log(href);
})
})
出力:これは全部相対パスですか?腫れはどうすればいいですか?急がないでください.urlモジュールがあります.
// ---------- 3 -------------
var href = url.resolve(targetUrl, $(element).attr('href'));
続いてプログラム出力を実行します.urlsを取得するのは最初のステップだけです.ここでurlsが指すページの内容を取得します.例えば、二次ページのタイトルと最初のコメントを取得してから印刷します.
ここでは、eventproxyモジュールに参加して、指定回数非同期を優雅に制御した後、コールバック関数を実行します.
// ---------- 4 -------------
// eventproxy
var topicUrls = [];
function getTopicUrls() {
// ----3----
};
getTopicUrls()
var ep = new eventproxy();
// eventproxy
ep.after('crawled', topicUrls.length, function(topics) {
topics = topics.map(function(topicPair) {
var topicUrl = topicPair[0];
var topicHtml = topicPair[1];
var $ = cheerio.load(topicHtml);
return ({
title: $('.topic_full_title').text(),
href: topicUrl,
comment1: $('.reply_content .markdown-text').eq(0).text().trim()
});
});
console.log('outcome');
console.log(topics);
});
topicUrls.forEach(function(topicUrl) {
superagent.get(topicUrl)
.end(function(err, res){
console.log('fetch--' + topicUrl + '--successfully');
// eventproxy after , , ,
ep.emit('crawled', [topicUrl, res.text]);
});
});
出力:えっと、ここはoutcomeが空いていますか?何の鬼ですか?またコードを確認しました.shit非同期をコントロールしていないので、topicUrls.forEach()を実行する時、topicUrlsは空です.もちろんですか?全部ありません.神器promiseに加入して改良してみましょう.
//---------- 5 -----------
// promise
var topicUrls = [];
function getTopicUrls() {
return new Promise(function(resolve){
... // ----4----
});
};
getTopicUrls().then(function(topicUrls){
... // ----4----
})
出力:サプライズが来ました.ページには私たちが望むタイトル、url、コメントが出ていますが、予想に合わない点があります.出力ログをよく見てください.空いている対象文字列がたくさんあります.
ページはアクセスできませんか?
私達はこの出力していないページをコピーして、ブラウザで車を返すと、ページは実際にアクセスできます.ブラウザでは一回だけお願いします.爬虫類プログラムでは、nodeの高合併特性のため、同じ時間に何度もお願いします.サーバーの負荷を超えると、サーバーが崩壊します.ですから、サーバーには一般的にアンチ爬虫法がありますが、私たちはたまたまこのような状況に遭遇しました.どうやって証明しますか?私たちはurlsが指すすべてのページを直接出力します.(tips:terminalは出力が多すぎるので、linuxコマンド_;lessを使って、出力ログのページをめくることを制御できます.)
出力をよく見ると、すぐに以下のログが見つかります.
ページは全部503です.つまりサーバーは私たちの訪問を拒否しました.
私達は私達のプログラムを改良して、asyncは登場して、プログラムの合併を制御して、そして遅延を設定します.
// ---------- 6 -----------
// , 5
//
var topicUrls = [];
function getTopicUrls() {
return new Promise(function(resolve){
superagent.get(targetUrl)
.end(function(err, res){
if (err) {
return console.log('error:', err)
}
var $ = cheerio.load(res.text);
$('#topic_list .topic_title').each(function(index, element){
var href = url.resolve(targetUrl, $(element).attr('href'));
topicUrls.push(href);
resolve(topicUrls);
})
});
});
};
getTopicUrls().then(function(topicUrls){
var ep = new eventproxy();
ep.after('crawled', topicUrls.length, function(topics) {
topics = topics.map(function(topicPair) {
var topicUrl = topicPair[0];
var topicHtml = topicPair[1];
var $ = cheerio.load(topicHtml);
return ({
title: $('.topic_full_title').text(),
href: topicUrl,
comment1: $('.reply_content .markdown-text').eq(0).text().trim()
});
});
console.log('------------------------ outcomes -------------------------');
console.log(topics);
console.log(' ' + topics.length + ' ')
});
var curCount = 0;
//
function concurrentGet(url, callback) {
var delay = parseInt((Math.random() * 30000000) % 1000, 10);
curCount++;
setTimeout(function() {
console.log(' ', curCount, ', ', url, ', ' + delay + ' ');
superagent.get(url)
.end(function(err, res){
console.log('fetch--' + url + '--successfully');
ep.emit('crawled', [url, res.text]);
});
curCount--;
callback(null,url +'Call back content');
}, delay);
}
// async
// mapLimit(arr, limit, iterator, [callback])
//
async.mapLimit(topicUrls, 5 ,function (topicUrl, callback) {
concurrentGet(topicUrl, callback);
});
})
出力ログをもう一度見てください.強迫症の患者は気持ちがいいです.
ちょっと待ってください.もう一つのポイントがあります.多くのプログラム猿オタクにとって(ここでは万字を省略します)、上の基礎があります.爬虫類とストレージを実現するのも簡単です.例えば、先ほど話した例の中の二級ページの作者の顔写真をダウンロードします.ページを分析する手順は多く説明を加えなくて、直接コードをつけます.
var dir = './images'
//
mkdir(dir, function(err) {
if(err) {
console.log(err);
}
});
//---------- 7 -----------
// , 5
//
var topicUrls = [];
function getTopicUrls() {
return new Promise(function(resolve){
...// ---6---
});
};
getTopicUrls().then(function(topicUrls){
var ep = new eventproxy();
ep.after('crawled', topicUrls.length, function(topics) {
var imgUrls = []
topics = topics.map(function(topicPair) {
...// ---6---
imgUrls.push($('.user_avatar img').attr('src'));
});
// , async.mapSeries
async.mapSeries(imgUrls, function (imgUrl, callback) {
//
const stream = fs.createWriteStream(dir + '/' + path.basename(imgUrl) + '.jpg');
const res = superagent.get(imgUrl);
// res.type('jpg')
res.pipe(stream);
console.log(imgUrl, '-- ');
callback(null, 'Call back content');
});
console.log('------------------------ outcomes -------------------------');
console.log(' ' + topics.length + ' ');
});
var curCount = 0;
//
function concurrentGet(url, callback) {
...// ---6---
}
// async
async.mapLimit(topicUrls, 5 ,function (topicUrl, callback) {
concurrentGet(topicUrl, callback);
});
})
プログラムを実行すると、イメージフォルダの下に写真がたくさんあります.