昨日までのはこちら
100日後にエンジニアになるキミ - 70日目 - プログラミング - スクレイピングについて
100日後にエンジニアになるキミ - 66日目 - プログラミング - 自然言語処理について
100日後にエンジニアになるキミ - 63日目 - プログラミング - 確率について1
100日後にエンジニアになるキミ - 59日目 - プログラミング - アルゴリズムについて
100日後にエンジニアになるキミ - 53日目 - Git - Gitについて
100日後にエンジニアになるキミ - 42日目 - クラウド - クラウドサービスについて
100日後にエンジニアになるキミ - 36日目 - データベース - データベースについて
100日後にエンジニアになるキミ - 24日目 - Python - Python言語の基礎1
100日後にエンジニアになるキミ - 18日目 - Javascript - JavaScriptの基礎1
100日後にエンジニアになるキミ - 14日目 - CSS - CSSの基礎1
100日後にエンジニアになるキミ - 6日目 - HTML - HTMLの基礎1
今回はスクレイピングの続きです。
通信について
Python言語でスクレイピングを行なっていきます。
スクレイピングでは通信を伴いますので
通信の仕組みを知っておく必要があります。
WEBサイトは世界中のサーバー上に置かれています。
WEBにおいて基本的にサーバとのやりとりはHTTP(HyperText Transfer Protocol)
というプロトコル(通信規約)
を用いて行い
ブラウザからサーバへの要求をリクエスト
サーバからブラウザへの応答をレスポンス
と呼んでいます。
WEB上での基本的なやりとりはリクエスト/レスポンス(R/R)で成立しており
基本的にはテキストメッセージを交換することにより、実現されています
サイト検索の例
ブラウザから検索ツールで検索を実行リクエスト
サーバは要求に対して結果を返答レスポンス
レスポンスを元にブラウザは検索結果を表示
HTTP通信
には、いくつかの仕様があり、リクエストの送り方が複数あります。
GET通信
GETはURLにパラメータを付加してリクエストします
例:
http://otupy.com?p=abc&u=u123
?以降はパラメータでパラメータはキー=値
を&
つなぎにしたものです。
POST通信
POSTはBodyに含めてリクエストします
リクエストBody
param:p:ab,u:u123
POSTとGETの使い分け
通信自体はブラウザーでは適切な通信方法を選んで行うが
プログラムでは通信方法を指定する必要があります。
リクエスト
ブラウザーなどからWEBサイトのサーバーへの要求をリクエストと言っています。
ブラウザでWebページを開く際、ブラウザはサーバに下記のような要求メッセージを送信します。
GETの例:
リクエストヘッダ
GET http://www.otupy.com/ex/http.htm HTTP/1.1
Host: www.otupy.com
Proxy-Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8
Referer: https://www.google.co.jp/
Accept-Encoding: gzip, deflate
Accept-Language: ja,en-US;q=0.9,en;q=0.8
POSTの例:
リクエストヘッダ:
POST /hoge/ HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 22
Cache-Control: max-age=0
Origin: http://localhost:8080
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8
Referer: http://localhost:8080/hoge/
Accept-Encoding: gzip, deflate, br
Accept-Language: ja,en-US;q=0.8,en;q=0.6
リクエストボディ:
name=hoge&comment=hoge
リクエストはヘッダ
とボディ
部があり、通信方法によってどのような情報を詰めて送信しているのかが変わります。
そのため、プログラムでアクセスする際にも適切な情報を詰めてリクエストをしてあげる必要があります。
プログラムでのアクセス
早速スクレイピングを試してみましょう。
Pythonではrequests
と言うライブラリで通信を行うことができます。
import requests
アクセス先のWEBサイトが必要なのでそれを指定してGET
で通信を行います。
requests.get(URL)
url = 'http://www.otupy.net/'
res = requests.get(url)
print(res)
通信の結果レスポンス
が返ってきます。
通信に成功していれば、アクセス先の情報が取得できます。
当然通信ですので失敗することもあります。
通信結果(レスポンス)
通信の結果レスポンス
はいくつかのステータスコードに別れます。
200番台は通信が成功していますが、400,500番台は
通信に失敗をしているので、URLの打ち間違いや、相手型のサーバーにアクセスできる状況であるのかを確認する必要があります。
分類 | 番号 | メッセージ | 説明 |
---|---|---|---|
情報 | 100 | Continue | 処理を継続しています。続きのリクエストを送信してください。 |
情報 | 101 | Sitching Protocols | Upgrade ヘッダで指定したプロトコルに変更して再要求してください。 |
成功 | 200 | OK | 成功しました。 |
成功 | 201 | Created | Location ヘッダで指定した場所に新しいコンテンツが作成されました。 |
成功 | 202 | Accepted | 要求は受理されました。ただし処理は完了していません。 |
成功 | 203 | Non-Authoritative Information | 応答ヘッダはオリジナルサーバーが返したものとは異なりますが、処理は成功です。 |
成功 | 204 | No Content | コンテンツはありませんが、処理は成功しました。 |
成功 | 205 | Reset Content | 要求を受理したので、現在のコンテンツ(画面)を破棄してください。。 |
成功 | 206 | Partial Content | コンテンツを一部のみ返却します。 |
転送 | 300 | Multiple Choices | コンテンツ入手方法について複数の選択肢があります。 |
転送 | 301 | Moved Permanently | Location ヘッダで指定された別の場所に移動しました。 |
転送 | 302 | Found | Location ヘッダで指定された別の場所に見つかりました。そちらを見てください。 |
転送 | 303 | See Other | Location ヘッダで指定された他の場所を見てください。 |
転送 | 304 | Not Modified | 更新されていません。If-Modified-Since ヘッダを用いた場合に返却されます。 |
転送 | 305 | Use Proxy | Location ヘッダで指定したプロキシを使用してください。 |
転送 | 306 | (Unused) | 未使用。 |
転送 | 307 | Temporary Redirect | 別の場所に一時的に移動しています。 |
クライアントエラー | 400 | Bad Request | 要求が不正です。 |
クライアントエラー | 401 | Unauthorized | 認証されていません。 |
クライアントエラー | 402 | Payment Required | 支払いが必要です。 |
クライアントエラー | 403 | Forbidden | アクセスが認められていません。 |
クライアントエラー | 404 | Not Found | 見つかりません。 |
クライアントエラー | 405 | Method Not Allowed | 指定したメソッドはサポートされていません。 |
クライアントエラー | 406 | Not Acceptable | 許可されていません。 |
クライアントエラー | 407 | Proxy Authentication Required | プロキシ認証が必要です。 |
クライアントエラー | 408 | Request Timeout | リクエストがタイムアウトしました。 |
クライアントエラー | 409 | Conflict | リクエストがコンフリクト(衝突・矛盾)しました。 |
クライアントエラー | 410 | Gone | 要求されたコンテンツは無くなってしまいました。 |
クライアントエラー | 411 | Length Required | Content-Length ヘッダを付加して要求してください。 |
クライアントエラー | 412 | Precondition Failed | If-... ヘッダで指定された条件に合致しませんでした。 |
クライアントエラー | 413 | Request Entity Too Large | 要求されたエンティティが大きすぎます。 |
クライアントエラー | 414 | Request-URI Too Long | 要求された URI が長すぎます。 |
クライアントエラー | 415 | Unsupported Media Type | サポートされていないメディアタイプです。 |
クライアントエラー | 416 | Requested Range Not Satisfiable | 要求されたレンジが不正です。 |
クライアントエラー | 417 | Expectation Failed | Expect ヘッダで指定された拡張要求は失敗しました。 |
サーバーエラー | 500 | Internal Server Error | サーバーで予期しないエラーが発生しました。 |
サーバーエラー | 501 | Not Implemented | 実装されていません。 |
サーバーエラー | 502 | Bad Gateway | ゲートウェイが不正です。 |
サーバーエラー | 503 | Service Unavailable | サービスは利用可能ではありません。 |
サーバーエラー | 504 | Gateway Timeout | ゲートウェイがタイムアウトしました。 |
サーバーエラー | 505 | HTTP Version Not Supported | このHTTPバージョンはサポートされていません。 |
プログラムでの通信結果の確認
さてプログラムで通信の結果を確認してみましょう。
レスポンス変数.status_code
でステータスコードを確認できます。
url = 'http://www.otupy.net/'
res = requests.get(url)
print(res.status_code)
200
もし200番でなければ通信が失敗しているのでWEBサイトの情報取得は出来ていないことになります。
200番の場合は通信が成功しているのでWEBサイトから取得した情報を見ることができます。
通信の結果を変数に格納しているので、様々な内容を見ることが出来ます。
リクエストURL
レスポンス変数.url
ステータスコード
レスポンス変数.status_code
レスポンスボディをテキスト形式で取得
レスポンス変数.text
レスポンスボディをバイナリ形式で取得
レスポンス変数.content
クッキー
レスポンス変数.cookies
エンコーディング情報を取得
レスポンス変数.encoding
ここから先は取得したテキスト情報を使って必要な情報に切り分けていきます。
# レスポンスをバイナリ形式で取得して文字に変換して表示(1000文字分)
print(res.content[0:1000].decode('utf-8'))
....
カスタムヘッダー
リクエストを行う際にはリクエストヘッダとボディ部に情報を詰めてリクエストすることができます。
GET通信でヘッダを指定してリクエストするには下記のように行います。
requests.get(url, headers=辞書型のヘッダデータ)
ヘッダ情報としてユーザーエージェント
を変更してアクセスするにはこのように指定します。
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36 '}
res = requests.get(url, headers=headers)
GET通信でパラメータを変更して通信する場合は以下のように指定します。
requests.get(url, params=辞書型のパラメータデータ)
params = {'key1': 'value1', 'key2': 'value2'}
res = requests.get(url, params=params)
POST通信でリクエストボディ部に情報を詰めてリクエストするには下記のように行います。
requests.get(url, data=辞書型のボディデータ)
payload = {'send': 'data'}
res = requests.post(url, data=payload)
まとめ
スクレイピングに必要な通信の仕組みを抑えておき情報取得が出来るようになっておこう。明日はこの続きで取得した情報から必要な情報を抜き出すところに入っていきます。
君がエンジニアになるまであと29日
作者の情報
乙pyのHP:
http://www.otupy.net/
Youtube:
https://www.youtube.com/channel/UCaT7xpeq8n1G_HcJKKSOXMw
Twitter:
https://twitter.com/otupython