TODO-4:nodejsが漫画の登取を実現


昔から声のある本を聴くのが好きでしたが、そのオーディオを探すのに苦労しました.しかし、探しているうちに、私はオーディオをダウンロードするたびに同じ操作を繰り返していることに気づいたので、プログラムで実現できるかどうか考えました.その時は実現する気が強くなかったのがこのツールだったので、考えのレベルにとどまっただけです.
最近何気なく1部の感じの良いアニメ《镇魂街》を発见して、アニメを见てから中毒にならないと感じて、また公式の漫画版がまだ见応えがあることを発见して、そこでまた最初から后で漫画をやめて、しかし1ページ1ページのひっくり返って探すのが疲れていることを発见して、だからまたこれらのピクチャーを一度にdownしてどれだけ爽やかになるべきだと思っています.
ちょうど手元にng 2のプロジェクトがあって、そこでこのフレームワークを借りてこの漫画を這い出してみて、広告がなくて、接続がなくて、簡単で乱暴で直接図を見ます.
Webページをキャプチャするいくつかの必要なツールは、クライアントの代わりに1:superagent githubアドレスが要求を開始します.2:cheerio githubアドレス解析html 3:fs nodeのファイルシステムモジュール
まず安定点のウェブサイトを探して捕まえて、さもなくばちょうどどのようにこのウェブサイトの下のページを解析することを研究して、結果はページが不安定で、むだです.解析の構想はきっと順序で、まず1部の漫画の章節を探し出して、それから各章節によって中のピクチャーをダウンロードします.
次に、私が捕まえる過程で出会ったいくつかの小さな問題について話します.1:符号化の問題;デフォルトではsuperagentはutf-8の符号化ですが、サイトの符号化がutf-8でないとキャプチャされたページが文字化けしてしまい、解析しにくくなります.このような場合、リクエストを開始するときに符号化設定を追加することができます.これは、superagent-charset、githubアドレス、乱符号化防止用の4つ目の必要なツールに関連しています.2:要求ヘッダの問題;一般的にこのようなサイトには防犯チェーンの措置があるので、勝手に要求するとすぐに逆ルートになるので、最も安全な案はブラウザで捕まえる必要があるページを開いて、対応するネットワーク要求ヘッドを見つけて、全copyを降りますが、特にあるReferというフィールドは固定的な接続ですが、章によっては章ごとに違います.3:「順序」を要求するか、「同時」を要求するかは、最初は同時形式でキャプチャされますが、キャプチャされた画像が不完全な現象が発生します.このような状況はまだ何が原因なのかよく分からない.しかし,順序を変えてリクエストごとに一定時間間隔を置いて,できるだけ実際の人工リクエストを模倣し,キャプチャ不全は発生しなかった.
主なコードロジックは次のとおりです.
要求ヘッダを統一的に設定する方法:
function makeReuest(option){
    return  request.get(option.url).charset('gbk')
    .set('Accept','text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8')
      // .set('Accept-Encoding','gzip, deflate, sdch')
      .set('Accept-Language','zh-CN,zh;q=0.8,en;q=0.6')
      .set('Cache-Control','no-cache')
      .set('Connection','keep-alive')
      .set('Cookie',option.cookie)
      .set('Host',option.host)
      .set('Pragma','no-cache')
      .set('Referer',option.referer)
      // .set('Upgrade-Insecure-Requests','1')
      .set('User-Agent','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36')
      .catch(option.cb)
      ;

  }

すべてのcallbackがpromise形式に移行
module.exports = function (func, option = {}) {
  return (...arg) => new Promise((resolve, reject) => {
    return func.apply(option.context, [...arg, (err, ...data) => {
      if (err) {
        return reject(err);
      }
      if (option.multiArg) {
        return resolve(data)
      }
      return resolve(data[0]);
    }]);
  })
}

書き込みロジック:

const writeFileAsync = promisify(fs.writeFile);
const mkdirAsync = promisify(fs.mkdir);

writeFileAsync(imgPath, _picRes.body)
        .then(function () {
          console.log('write OK:', imgPath)
        })
        .catch(function () {
          console.log('write err:', imgPath)
          mkdirAsync(path)
            .then(function () {
              return writeFileAsync(imgPath, _picRes.body)
            })
            .then(function () {
               console.log('write file retry finished:', imgPath)
            })
            .catch(function (err) {
              console.log('retry err', err)
              throw  err;
            });
        });