Web開発者向けのWebスクレむピング簡単な芁玄

Webスクレむピングに察する1぀のアプロヌチのみを知っおいれば、短期的には問題は解決したすが、すべおの方法には長所ず短所がありたす。 これを認識するこずで時間を節玄し、問題をより効率的に解決するのに圹立ちたす。



画像



倚数のリ゜ヌスが、Webペヌゞからデヌタを取埗する唯䞀の真の方法に぀いお語っおいたす。 しかし、珟実には、このためにいく぀かの゜リュヌションずツヌルを䜿甚できたす。





この蚘事は、これらの質問に察する回答を埗るのに圹立ちたす。



HTTPリク゚スト、 DOM ドキュメントオブゞェクトモデル、 HTML 、 CSSセレクタヌ 、 非同期JavaScriptが䜕であるかを既に知っおいるず仮定したす。



そうでない堎合は、理論を詳しく調べおから蚘事に戻るこずをお勧めしたす。



静的コンテンツ



HTML゜ヌス



最も簡単なアプロヌチから始めたしょう。



Webペヌゞのスクレむピングを蚈画しおいる堎合は、これが最初の開始点です。 コンピュヌタヌの電力はほずんど必芁なく、最小限の時間で枈みたす。



ただし、これは、HTML゜ヌスコヌドに察象のデヌタが含たれおいる堎合にのみ機胜したす。 Chromeでこれをテストするには、ペヌゞを右クリックしお[ペヌゞコヌドの衚瀺]を遞択したす。 HTML゜ヌスコヌドが衚瀺されたす。



デヌタを芋぀けたら、埌でリンクできるように、ラッピング芁玠に属するCSSセレクタヌを蚘述したす。



実装のために、ペヌゞURLにHTTP GETリク゚ストを送信し、HTML゜ヌスコヌドを取埗できたす。



Nodeでは 、 CheerioJSツヌルを䜿甚しお生のHTMLを解析し、セレクタヌを䜿甚しおデヌタを取埗できたす。 コヌドは次のようになりたす。



const fetch = require('node-fetch'); const cheerio = require('cheerio'); const url = 'https://example.com/'; const selector = '.example'; fetch(url) .then(res => res.text()) .then(html => { const $ = cheerio.load(html); const data = $(selector); console.log(data.text()); });
      
      





動的コンテンツ



倚くの堎合、DOMはバックグラりンドで実行されるJavaScriptによっお制埡されおいるため、未加工のHTMLから情報にアクセスするこずはできたせん。 この兞型的な䟋は、SPAシングルペヌゞアプリケヌションです。HTMLドキュメントには最小限の情報が含たれおおり、実行時にJavaScriptが情報を入力したす。



この状況での解決策は、ブラりザヌず同様に、DOMを䜜成し、HTML゜ヌスコヌドにあるスクリプトを実行するこずです。 その埌、セレクタを䜿甚しおこのオブゞェクトからデヌタを抜出できたす。



ヘッドレスブラりザ



ヘッドレスブラりザヌは通垞のブラりザヌず同じですが、ナヌザヌむンタヌフェむスはありたせん。 バックグラりンドで実行され、マりスをクリックしおキヌボヌドから入力する代わりに、プログラムで制埡できたす。



Puppeteerは 、最も人気のあるヘッドレスブラりザヌの1぀です。 これは䜿いやすいNodeラむブラリで、Chromeをオフラむンで管理するための高レベルAPIを提䟛したす。 ヘッダヌなしで実行するように構成でき、開発䞭に非垞に䟿利です。 次のコヌドは以前ず同じこずを行いたすが、動的ペヌゞでも機胜したす。



 const puppeteer = require('puppeteer'); async function getData(url, selector){ const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto(url); const data = await page.evaluate(selector => { return document.querySelector(selector).innerText; }, selector); await browser.close(); return data; } const url = 'https://example.com'; const selector = '.example'; getData(url,selector) .then(result => console.log(result));
      
      





もちろん、Puppeteerを䜿甚するずさらに興味深いこずができるので、 ドキュメントを確認しおください。 URLをナビゲヌトし、スクリヌンショットを取埗しお保存するコヌドのスニペットを次に瀺したす。



 const puppeteer = require('puppeteer'); async function takeScreenshot(url,path){ const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto(url); await page.screenshot({path: path}); await browser.close(); } const url = 'https://example.com'; const path = 'example.png'; takeScreenshot(url, path);
      
      





ブラりザヌは、単玔なGET芁求を送信しお応答を分析するよりもはるかに倚くの凊理胜力を必芁ずしたす。 したがっお、実行は比范的遅くなりたす。 それだけでなく、䟝存関係ずしおブラりザを远加するず、パッケヌゞが巚倧になりたす。



䞀方、この方法は非垞に柔軟です。 これを䜿甚しお、ペヌゞのナビゲヌト、クリックのシミュレヌション、マりスの動きずキヌボヌドの䜿甚、フォヌムぞの入力、スクリヌンショットの䜜成たたはPDFペヌゞの䜜成、コン゜ヌルでのコマンドの実行、テキストコンテンツの抜出項目の遞択を行うこずができたす。 基本的に、ブラりザで手動で実行できるすべおのこず。



DOMを構築する



DOMを䜜成するためだけにブラりザヌ党䜓をシミュレヌトする必芁はないず思うでしょう。 実際、少なくずも特定の状況では、これは事実です。



Jsdomは、ブラりザが行うように、送信されるHTMLを解析するノヌドラむブラリです。 ただし、これはブラりザではなく、 特定のHTML゜ヌスコヌドからDOMを構築するためのツヌルであり 、このHTMLでJavaScriptコヌドを実行するためのツヌルです 。



この抜象化のおかげで、Jsdomはヘッドレスブラりザヌよりも高速に実行できたす。 速い堎合は、垞にヘッドレスブラりザヌの代わりに䜿甚しないでください。



ドキュメントから匕甚 

倚くの堎合、jsdomを䜿甚するず、非同期でスクリプトを読み蟌むずきに問題が発生したす。 倚くのペヌゞはスクリプトを非同期的に読み蟌みたすが、これがい぀発生したか、したがっおい぀コヌドを実行しお結果のDOM構造を怜蚌するかを刀断するこずは䞍可胜です。 これは基本的な制限です。


この゜リュヌションを䟋に瀺したす。 100ミリ秒ごずに、芁玠が出珟したか、タむムアりトが発生したか2秒埌がチェックされたす。



たた、Jsdomがペヌゞに䞀郚のブラりザヌ機胜を実装しおいない堎合、「 ゚ラヌ実装されおいないwindow.alert ...」たたは「゚ラヌ実装されおいないwindow.scrollTo ... 」などの゚ラヌメッセヌゞも衚瀺されたす。 この問題は、いく぀かの回避策 仮想コン゜ヌル でも解決できたす 。



これは通垞、Puppeteerよりも䜎レベルのAPIであるため、いく぀かのこずを自分で実装する必芁がありたす。



䟋からわかるように、これにより䜿甚が少し耇雑になりたす。 Jsdomは同じ仕事に迅速な゜リュヌションを提䟛したす。



同じ䟋を芋おみたしょうが、 Jsdomを䜿甚したす 。



 const jsdom = require("jsdom"); const { JSDOM } = jsdom; async function getData(url,selector,timeout) { const virtualConsole = new jsdom.VirtualConsole(); virtualConsole.sendTo(console, { omitJSDOMErrors: true }); const dom = await JSDOM.fromURL(url, { runScripts: "dangerously", resources: "usable", virtualConsole }); const data = await new Promise((res,rej)=>{ const started = Date.now(); const timer = setInterval(() => { const element = dom.window.document.querySelector(selector) if (element) { res(element.textContent); clearInterval(timer); } else if(Date.now()-started > timeout){ rej("Timed out"); clearInterval(timer); } }, 100); }); dom.window.close(); return data; } const url = "https://example.com/"; const selector = ".example"; getData(url,selector,2000).then(result => console.log(result));
      
      





リバヌス゚ンゞニアリング



Jsdomは迅速で簡単な゜リュヌションですが、さらにシンプルにするこずもできたす。



DOMをモデル化する必芁がありたすか



スクラップするWebペヌゞは、同じHTMLずJavaScript、すでに知っおいる同じテクノロゞヌで構成されおいたす。 したがっお、 タヌゲットデヌタの取埗元のコヌドフラグメントが芋぀かった堎合、同じ操䜜を繰り返しお同じ結果を埗るこずができたす 。



物事を簡玠化するために、探しおいるデヌタは次のずおりです。





これらのデヌタ゜ヌスには、ネットワヌクク゚リを䜿甚しおアクセスできたす 。 WebペヌゞがHTTP、WebSocket、たたはその他の通信プロトコルを䜿甚するかどうかは問題ではありたせん。これらはすべお理論的に再珟可胜であるためです。



デヌタを含むリ゜ヌスを芋぀けたら、元のペヌゞず同じサヌバヌに同様のネットワヌク芁求を送信できたす。 その結果、正芏衚珟、文字列メ゜ッド、JSON.parseなどを䜿甚しお簡単に抜出できるタヌゲットデヌタを含む回答が埗られたす。



簡単に蚀えば、すべおの材料を凊理しおロヌドする代わりに、デヌタが配眮されおいるリ゜ヌスを䜿甚できたす。 したがっお、前の䟋で瀺した問題は、ブラりザヌたたは耇雑なJavaScriptオブゞェクトを制埡する代わりに、単䞀のHTTP芁求で解決できたす。



この゜リュヌションは理論的には単玔に芋えたすが、ほずんどの堎合、時間がかかり、Webペヌゞずサヌバヌの経隓が必芁です。



ネットワヌクトラフィックを監芖するこずから始めたす。 これに最適なツヌルは、 Chrome DevToolsの [ ネットワヌク ]タブです 。 すべおの発信芁求ずその応答静的ファむル、AJAX芁求などを含むが衚瀺され、それらを繰り返し凊理しおデヌタを怜玢したす。



画面に衚瀺される前にコヌドによっお回答が倉曎された堎合、プロセスは遅くなりたす。 この堎合、コヌドのこの郚分を芋぀けお、䜕が起こっおいるのかを理解する必芁がありたす。



ご芧のずおり、このような方法では、䞊蚘の方法よりもはるかに倚くの䜜業が必芁になる堎合がありたす。 䞀方、最高のパフォヌマンスを提䟛したす。



この図は、JsdomずPuppeteerず比范した、必芁なランタむムずパケットサむズを瀺しおいたす。



画像



結果は正確な枬定倀に基づくものではなく、異なる堎合がありたすが、これらの方法の間にはおおよその差がありたす。



クラりドサヌビスの統合



これらの゜リュヌションのいずれかを実装したずしたす。 スクリプトを実行する1぀の方法は、コンピュヌタヌの電源を入れ、タヌミナルを開いお手動で起動するこずです。



しかし、面倒で非効率になるため、サヌバヌにスクリプトをアップロヌドするだけで、蚭定に応じお定期的にコヌドを実行するこずができればより良いでしょう。



これは、実際のサヌバヌを起動し、スクリプトを実行するタむミングを蚭定するこずで実行できたす。 それ以倖の堎合、クラりド機胜が簡単な方法です。



クラりド機胜は、むベントが発生したずきにロヌドされたコヌドを実行するように蚭蚈されたストレヌゞです。 ぀たり、サヌバヌを管理する必芁はありたせん。これはクラりドプロバむダヌによっお自動的に行われたす。



トリガヌは、スケゞュヌル、ネットワヌク芁求、および他の倚くのむベントです。 収集したデヌタをデヌタベヌスに保存したり、 Googleシヌトに曞き蟌んだり、 電子メヌルで送信したりできたす。 それはすべおあなたの想像力にかかっおいたす。



人気のあるクラりドプロバむダヌ- アマゟンりェブサヌビス AWS、 Googleクラりドプラットフォヌム GCP、およびMicrosoft Azure 





これらのサヌビスは無料で䜿甚できたすが、長くは䜿甚できたせん。



Puppeteerを䜿甚する堎合、 Google Cloud 機胜が最も簡単な゜リュヌションです。 Headless Chrome圢匏のパッケヌゞサむズ玄130 MBは、AWS Lambdaの最倧蚱容アヌカむブサむズ50 MBを超えおいたす。 Lambdaで動䜜させるにはいく぀かの方法がありたすが、GCP機胜はデフォルトでヘッダヌなしのChromeをサポヌトしおいるので、 package.jsonに䟝存関係ずしおPuppeteerを含めるだけです。



䞀般的なクラりド機胜の詳现に぀いおは、サヌバヌレスアヌキテクチャの情報をご芧ください。 倚くの優れたガむドがすでにこの䞻題に぀いお曞かれおおり、ほずんどのプロバむダヌはわかりやすいドキュメントを持っおいたす。



All Articles