PythonWebスクレイピング-動的Webサイト

この章では、動的WebサイトでWebスクレイピングを実行する方法と、関連する概念について詳しく学びましょう。

前書き

Webスクレイピングは複雑なタスクであり、Webサイトが動的である場合、複雑さは倍増します。国連のWebアクセシビリティのグローバル監査によると、Webサイトの70%以上は本質的に動的であり、機能をJavaScriptに依存しています。

動的Webサイトの例

動的なWebサイトの例を見て、スクレイプが難しい理由を知ってみましょう。ここでは、という名前のWebサイトから検索する例を取り上げます。http://example.webscraping.com/places/default/search.しかし、このWebサイトは動的な性質のものであるとどのように言えますか?上記のウェブページからデータをスクレイピングしようとする次のPythonスクリプトの出力から判断できます-

import re
import urllib.request
response = urllib.request.urlopen('http://example.webscraping.com/places/default/search')
html = response.read()
text = html.decode()
re.findall('(.*?)',text)

出力

[ ]

上記の出力は、検索しようとしている<div>要素が空であるため、サンプルのスクレーパーが情報の抽出に失敗したことを示しています。

動的Webサイトからデータをスクレイピングするためのアプローチ

データはJavaScriptで動的に読み込まれるため、スクレーパーは動的なWebサイトから情報を取得できないことがわかりました。このような場合、動的なJavaScriptに依存するWebサイトからデータをスクレイピングするために次の2つの手法を使用できます。

  • リバースエンジニアリングJavaScript
  • JavaScriptのレンダリング

リバースエンジニアリングJavaScript

リバースエンジニアリングと呼ばれるプロセスは便利であり、データがWebページによって動的にロードされる方法を理解できます。

これを行うには、をクリックする必要があります inspect element指定されたURLのタブ。次に、クリックしますNETWORK タブをクリックして、パスがのsearch.jsonを含むそのWebページに対して行われたすべてのリクエストを検索します。 /ajax。ブラウザまたは[ネットワーク]タブからAJAXデータにアクセスする代わりに、Pythonスクリプトに従うことでアクセスできます-

import requests
url=requests.get('http://example.webscraping.com/ajax/search.json?page=0&page_size=10&search_term=a')
url.json()

上記のスクリプトを使用すると、Pythonjsonメソッドを使用してJSON応答にアクセスできます。同様に、生の文字列応答をダウンロードでき、Pythonのjson.loadsメソッドを使用してロードすることもできます。次のPythonスクリプトを使用してこれを行っています。基本的に、アルファベットの「a」の文字を検索し、JSON応答の結果のページを繰り返すことにより、すべての国をスクレイプします。

import requests
import string
PAGE_SIZE = 15
url = 'http://example.webscraping.com/ajax/' + 'search.json?page={}&page_size={}&search_term=a'
countries = set()
for letter in string.ascii_lowercase:
   print('Searching with %s' % letter)
   page = 0
   while True:
   response = requests.get(url.format(page, PAGE_SIZE, letter))
   data = response.json()
   print('adding %d records from the page %d' %(len(data.get('records')),page))
   for record in data.get('records'):countries.add(record['country'])
   page += 1
   if page >= data['num_pages']:
      break
   with open('countries.txt', 'w') as countries_file:
   countries_file.write('n'.join(sorted(countries)))

上記のスクリプトを実行すると、次の出力が得られ、レコードはcountries.txtという名前のファイルに保存されます。

出力

Searching with a
adding 15 records from the page 0
adding 15 records from the page 1
...

JavaScriptのレンダリング

前のセクションでは、APIがどのように機能し、APIを使用して単一のリクエストで結果を取得する方法について、Webページでリバースエンジニアリングを行いました。ただし、リバースエンジニアリングを行うと次のような問題に直面する可能性があります。

  • 時々ウェブサイトは非常に難しい場合があります。たとえば、WebサイトがGoogle Web Toolkit(GWT)などの高度なブラウザツールで作成されている場合、結果のJSコードはマシンで生成され、理解してリバースエンジニアリングするのが困難になります。

  • のようないくつかのより高いレベルのフレームワーク React.js すでに複雑なJavaScriptロジックを抽象化することにより、リバースエンジニアリングを困難にする可能性があります。

上記の問題の解決策は、HTMLを解析し、CSSフォーマットを適用し、JavaScriptを実行してWebページを表示するブラウザーレンダリングエンジンを使用することです。

この例では、Javaスクリプトをレンダリングするために、おなじみのPythonモジュールSeleniumを使用します。次のPythonコードは、Seleniumの助けを借りてWebページをレンダリングします-

まず、次のようにセレンからWebドライバーをインポートする必要があります-

from selenium import webdriver

次に、要件に従ってダウンロードしたWebドライバーのパスを入力します-

path = r'C:\\Users\\gaurav\\Desktop\\Chromedriver'
driver = webdriver.Chrome(executable_path = path)

次に、Pythonスクリプトによって制御されているWebブラウザーで開きたいURLを指定します。

driver.get('http://example.webscraping.com/search')

これで、検索ツールボックスのIDを使用して、選択する要素を設定できます。

driver.find_element_by_id('search_term').send_keys('.')

次に、Javaスクリプトを使用して、選択ボックスの内容を次のように設定できます。

js = "document.getElementById('page_size').options[1].text = '100';"
driver.execute_script(js)

次のコード行は、検索がWebページでクリックされる準備ができていることを示しています-

driver.find_element_by_id('search').click()

次のコード行は、AJAXリクエストが完了するまで45秒待機することを示しています。

driver.implicitly_wait(45)

これで、国のリンクを選択するために、CSSセレクターを次のように使用できます-

links = driver.find_elements_by_css_selector('#results a')

これで、国のリストを作成するために各リンクのテキストを抽出できます-

countries = [link.text for link in links]
print(countries)
driver.close()