この記事では、Node Puppeteer 画像認識を使用して Baidu インデックス クローラーを実装する例を主に紹介します。編集者はそれが非常に優れていると考えたので、参考として共有します。編集者をフォローして見てみましょう
以前、さまざまな大手メーカーのフロントエンドのクロール対策技術を紹介した啓発的な記事を読みましたが、この記事にあるように、100% のクロール対策方法はありません。記事 これらのフロントエンドのクローラー対策メソッドをすべてバイパスする簡単な方法を紹介します。
次のコードは Baidu Index を例にしています。コードは Baidu Index クローラー ノード ライブラリにパッケージ化されています: https://github.com/Coffcer/baidu-index-spider
注: クローラーを悪用しないでください。
Baidu Index のクローラー対策戦略
Baidu Index のインターフェイスを観察すると、特定の日にマウスを置くと、2 つのリクエストがトリガーされます。結果はフローティング ボックスに表示されます:
一般的な考え方に従って、まずこのリクエストの内容を見てみましょう:
リクエスト 1:
リクエスト 2:
Baidu Index が実際にフロントエンドのクローラー対策戦略に何らかの取り組みを行っていることがわかります。マウスがグラフ上に移動すると、2 つのリクエストがトリガーされ、1 つのリクエストは HTML を返し、もう 1 つのリクエストは生成された画像を返します。 html には実際の値は含まれていませんが、width と margin-left を設定することで、対応する文字が画像上に表示されます。さらに、リクエストパラメータには res や res1 など、シミュレート方法が不明なパラメータが含まれているため、従来のシミュレートされたリクエストや HTML クローリング方法を使用して Baidu Index データをクロールすることは困難です。
クローラーの考え
Baidu のクローラー対策方法を突破するにはどうすればよいでしょうか? それは実際には非常に簡単です。クローラー対策方法については気にしないでください。ユーザーの操作をシミュレートし、必要な値をスクリーンショットし、画像認識を行うだけで済みます。手順は大まかに:
ログインをシミュレートする
インデックスページを開く
指定した日付にマウスを移動する
リクエストが終了するのを待ち、数値部分の画像を傍受する
値を取得するための画像認識
ステップ 3 から 5 をループして、各日付に対応する値を取得します
このメソッドは理論的にはあらゆる Web サイトのコンテンツをクロールできます。 次に、次のようにクローラ ステップを実装します。次のライブラリが使用されます:
puppeteer ブラウザ操作をシミュレート
node-tesseract tesseractパッケージ、画像認識に使用されます
jimp 画像のトリミング
インストールPuppeteer 、ユーザー操作をシミュレートします
Puppeteer は、Google Chrome チームによって作成された Chrome 自動化ツールで、Chrome の実行コマンドを制御するために使用されます。ユーザー操作をシミュレートしたり、自動テストやクローラーなどを実行したりできます。使い方はとても簡単です。この記事を読めば使い方がわかると思います。
API ドキュメント: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md
インストール:
npm install --save puppeteer
Puppeteer は、正常な動作を確保するために、インストール中に Chromium を自動的にダウンロードします。ただし、国内ネットワークでは Chromium を正常にダウンロードできない場合があります。ダウンロードに失敗した場合は、cnpm を使用してインストールするか、ダウンロード アドレスを Taobao ミラーに変更してからインストールすることができます:
npm config set PUPPETEER_DOWNLOAD_HOST=https://npm.taobao.org/mirrors npm install --save puppeteer
Chromium のダウンロードをスキップすることもできます。インストール中にコードを渡します 実行するネイティブ Chrome パスを指定します:
// npm npm install --save puppeteer --ignore-scripts // node puppeteer.launch({ executablePath: '/path/to/Chrome' });
implementation
レイアウトをきれいに保つために、セレクターに関係するコードの部分のみを以下に示します。完全なコードについては、記事の上部にある github リポジトリを参照してください。
Baidu Index ページを開いてログインをシミュレートします
ここで行うのは、ユーザーの操作、クリックと入力を段階的にシミュレートすることです。ログイン認証コードを処理する必要はありません。認証コードの処理は別のトピックです。Baidu にローカルでログインしている場合、通常は認証コードは必要ありません。
// 启动浏览器, // headless参数如果设置为true,Puppeteer将在后台操作你Chromium,换言之你将看不到浏览器的操作过程 // 设为false则相反,会在你电脑上打开浏览器,显示浏览器每一操作。 const browser = await puppeteer.launch({headless:false}); const page = await browser.newPage(); // 打开百度指数 await page.goto(BAIDU_INDEX_URL); // 模拟登陆 await page.click('...'); await page.waitForSelecto('...'); // 输入百度账号密码然后登录 await page.type('...','username'); await page.type('...','password'); await page.click('...'); await page.waitForNavigation(); console.log(':white_check_mark: 登录成功');
マウスの移動をシミュレートして必要なデータを取得します
ページをトレンドチャート領域までスクロールし、マウスを特定の日付に移動し、リクエストが終了するまで待ちます。ツールチップに値が表示されます。そしてスクリーンショットを撮って画像を保存します。
// 获取chart第一天的坐标 const position = await page.evaluate(() => { const $image = document.querySelector('...'); const $area = document.querySelector('...'); const areaRect = $area.getBoundingClientRect(); const imageRect = $image.getBoundingClientRect(); // 滚动到图表可视化区域 window.scrollBy(0, areaRect.top); return { x: imageRect.x, y: 200 }; }); // 移动鼠标,触发tooltip await page.mouse.move(position.x, position.y); await page.waitForSelector('...'); // 获取tooltip信息 const tooltipInfo = await page.evaluate(() => { const $tooltip = document.querySelector('...'); const $title = $tooltip.querySelector('...'); const $value = $tooltip.querySelector('...'); const valueRect = $value.getBoundingClientRect(); const padding = 5; return { title: $title.textContent.split(' ')[0], x: valueRect.x - padding, y: valueRect.y, width: valueRect.width + padding * 2, height: valueRect.height } });
スクリーンショット
値の座標を計算し、スクリーンショットを撮り、jimp を使用して画像をトリミングします。
await page.screenshot({ path: imgPath }); // 对图片进行裁剪,只保留数字部分 const img = await jimp.read(imgPath); await img.crop(tooltipInfo.x, tooltipInfo.y, tooltipInfo.width, tooltipInfo.height); // 将图片放大一些,识别准确率会有提升 await img.scale(5); await img.write(imgPath);
画像認識
ここでは、画像認識に Tesseract を使用します。 Tesseracts は、画像内のテキストを識別するために使用され、トレーニングを通じて精度を向上させることができる、Google のオープンソース OCR ツールです。すでに github に単純なノード パッケージが存在します:node-tesseract。まず Tesseract をインストールし、環境変数に設定する必要があります。
Tesseract.process(imgPath, (err, val) => { if (err || val == null) { console.error(':x: 识别失败:' + imgPath); return; } console.log(val);
实际上未经训练的Tesseracts识别起来会有少数几个错误,比如把9开头的数字识别成`3,这里需要通过训练去提升Tesseracts的准确率,如果识别过程出现的问题都是一样的,也可以简单通过正则去修复这些问题。
封装
实现了以上几点后,只需组合起来就可以封装成一个百度指数爬虫node库。当然还有许多优化的方法,比如批量爬取,指定天数爬取等,只要在这个基础上实现都不难了。
const recognition = require('./src/recognition'); const Spider = require('./src/spider'); module.exports = { async run (word, options, puppeteerOptions = { headless: true }) { const spider = new Spider({ imgDir, ...options }, puppeteerOptions); // 抓取数据 await spider.run(word); // 读取抓取到的截图,做图像识别 const wordDir = path.resolve(imgDir, word); const imgNames = fs.readdirSync(wordDir); const result = []; imgNames = imgNames.filter(item => path.extname(item) === '.png'); for (let i = 0; i < imgNames.length; i++) { const imgPath = path.resolve(wordDir, imgNames[i]); const val = await recognition.run(imgPath); result.push(val); } return result; } }
反爬虫
最后,如何抵挡这种爬虫呢,个人认为通过判断鼠标移动轨迹可能是一种方法。当然前端没有100%的反爬虫手段,我们能做的只是给爬虫增加一点难度。
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
在Node.js中使用cheerio制作简单的网页爬虫(详细教程)
在React中使用Native如何实现自定义下拉刷新上拉加载的列表
以上がPuppeteer 画像認識テクノロジーを使用して Baidu インデックス クローラーを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。