LoginSignup
1
1

More than 3 years have passed since last update.

100日後にエンジニアになるキミ - 71日目 - プログラミング - スクレイピングについて2

Posted at

昨日までのはこちら

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'))

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "" class="autolink">http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
....

カスタムヘッダー

リクエストを行う際にはリクエストヘッダとボディ部に情報を詰めてリクエストすることができます。

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

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1