こんにちわ。初めて質問します。
PHPを学びはじめて二か月弱の者です。現在、ウェブサイトを巡回するプログラムを作ろうと考えています。
さて質問があります。
IDとパスワードを入力してログインするウェブサイトに対して、
プログラム(ウェブサイトを巡回するプログラム)からログインを行いたいです。
どのようなコードになるでしょうか?
なんとなく$_GETや$_POSTが出てきそうな予感がするのですが。……
勿論IDとパスワードは分かっているものとします。
やり方がわからず、もう二週間くらい悩んでいます。
よろしくお願いします。
No.4ベストアンサー
- 回答日時:
要点をまとめるとそんな感じですね。
多く書きすぎた気もしますが、中途半端に省略するとかえって疑問が生まれると思ったので詳しく回答させていただきました。cURLを使う方法がやっぱり一番書きやすくてオススメです。非同期通信に拘るときは fsockopen や stream_socket_client からローレベルな処理を書くときもありますが・・・下記の自作Twitterライブラリでは全ての通信をこれらの関数を使って行っていますね。
GitHub - TwistOAuth
https://github.com/Certainist/TwistOAuth
ソケットをオープンしている部分
https://github.com/Certainist/TwistOAuth/blob/ma …
スクレイピング認証(通称「疑似xAuth認証」)でレスポンスを解析している部分
https://github.com/Certainist/TwistOAuth/blob/ma …
No.3
- 回答日時:
連続回答失礼します。
(2番目の回答が「この投稿は、現在サポートで確認中のため、回答は他の方には表示されなくなっております。」となってしまいましたので表示されるまでお待ちください。)
1番目の回答に補足します。
以下の「レスポンス」とは、「レスポンスヘッダー」+「レスポンスボディ」のことを意味し、これらは "\r\n\r\n" で区切るようにして結合されています。
・fsockopenでつないだときのレスポンス
・stream_socket_clientでつないだときのレスポンス
一方以下のものは「レスポンスボディ」のみを意味します。レスポンスヘッダーは $http_response_header という予約済みの特殊な変数に自動的に配列でセットされています。
・fopenでつないだときのレスポンス
・file_get_contentsで得られるレスポンス
PHP Manual - $http_response_header
http://php.net/manual/ja/reserved.variables.http …
cURL利用時のレスポンスも「レスポンスボディ」のみを意味しますが、こちらではcurl_getinfo関数を使ってレスポンスヘッダーの取得を行います。
PHP Manual - curl_getinfo
http://php.net/manual/ja/function.curl-getinfo.php
この回答への補足
非常に詳しい解答ありがとうございます。
以下のような感じでよろしいでしょうか?
◆
プログラム(ウェブサイトを巡回するプログラム)からログインするには、「スクリプト」と「サイト」の間で通信を行う必要がある。
◆
やり方の概要としては。
1.
ログインフォームにGETでアクセスしてページ内容を取得する。多くの場合ではその中に不正アクセス対策のトークンが含まれている。この段階でサーバー側からCookieも送られてくる。
2.
ログインフォームに必要パラメータを添えてPOSTで送信する。必要パラメータは「不正アクセス対策のトークン」「ユーザーID」「パスワード」その他もろもろ。1で送信されてきたCookieを付加する必要がある。
3.
ログインが成功すれば、後は同じCookieを送信し続けるだけで会員専用ページなどの内容を取得することが出来る。
◆
上を実現するためのやり方は四つ。
・ fsockopen関数・stream_socket_client関数を利用する。
・ fopen関数を利用する。
・ file_get_contents関数を利用する。
・ cURL関数群を利用する。
◆
トークンを抽出するには、以下のやり方がある。
・正規表現を利用する(正規表現(せいきひょうげん、regular expression)とは、文字列の集合を一つ の文字列で表現する方法の一つである。ウィキペディア)
・ PHPネイティブのDOMを利用する
・ PHPネイティブのDOMとして読み込んだ後SimpleXMLに変換
・ Simple HTML DOM Parser を利用する
No.2
- 回答日時:
トークンを抽出する方法について。
ここでは以下のようなレスポンスボディを得たと仮定します。「token」が不正アクセス対策用のトークンです。<html>
<body>
<h1>ログインします</h1>
<form action="" method="POST">
<input type="text" name="id" value="">
<input type="password" name="pw" value="">
<input type="hidden" name="token" value="xxxxxxxxxx">
<input type="submit" value="送信">
</form>
</body>
</html>
● 正規表現を利用する
万能な「正規表現」の力を借りましょう。
Wikipedia - 正規表現
http://ja.wikipedia.org/wiki/%E6%AD%A3%E8%A6%8F% …
サルにもわかる正規表現入門
http://www.mnet.ne.jp/~nakama/
PHP Manual - PCRE正規表現構文
http://php.net/manual/ja/reference.pcre.pattern. …
PHP Manual - preg_match
http://php.net/manual/ja/function.preg-match.php
Qiita - 私の正規表現に関するポリシー
http://qiita.com/mpyw/items/8dd5378cb01c877e1f7b
[実装例]
PHPの正規表現に使うデリミタは「/」である必要は無く、ここではHTMLタグと重複しない「@」を選択することにします。
[^"]++
は「"」以外の文字の(バックトラック無効な)1回以上の繰り返しを表します。それを ( ) でくくることで、1番目の ( ) として $matches[1] にセットされるようにします。 ちなみに $matches[0] は全体を表します。
$pattern = '@<input type="hidden" name="token" value="([^"]++)">@';
if (!preg_match($pattern, $html, $matches)) {
throw new RuntimeException('トークン取得に失敗しました');
}
$token = $matches[1];
var_dump($token);
● PHPネイティブのDOMを利用する
正規表現を除けば、最も高速な方法です。
PHP Manual - Document Object Model
http://php.net/manual/ja/book.dom.php
PHP ARCHIVE - PHP で XML の内容を取得する(DOM, XPath)
http://php-archive.net/php/php-dom-xpath/
TECHSCORE - ロケーションパス
http://www.techscore.com/tech/XML/XPath/xpath02. …
1.
DOMDocumentオブジェクトを生成する。
2.
loadHTMLメソッドでHTMLとして強引に読み込む。HTMLが厳格に正しく書かれているかどうかの保証は無いので、不正構文で発生するエラーを「@」演算子で抑制する。
3.
DOMXPathオブジェクトなどを活用し、目的の値を取りに行く。queryメソッドが基本だが、evaluateメソッドが非常に強力で、使いこなせば複雑な処理をかなり短く書くことが出来る。
[実装例]
$xpath = new DOMXPath($dom = new DOMDocument);
@$dom->loadHTML($html);
if ('' === $token = $xpath->evaluate('string(//input[@name="token"]/@value)')) {
throw new RuntimeException('トークン取得に失敗しました');
}
var_dump($token);
● PHPネイティブのDOMとして読み込んだ後SimpleXMLに変換
XPathがSimpleXMLElementオブジェクト自体にメソッドとして内包されているなどの点をはじめ、DOMよりもSimpleXMLの方が使いやすく感じる箇所が多いと思います。但し、変換に少々コストがかかりますし、今回のサンプルのようにシンプルな例ではわざわざ使う必要もないでしょう。
PHP Manual - SimpleXML
http://php.net/manual/ja/book.simplexml.php
● Simple HTML DOM Parser を利用する
正規表現による一連の操作をラッピングし、もっと使いやすくなったDOMとして提供してくれるライブラリです。本当に使いやすいのですが、C言語コードの拡張としてではなくPHPのコードとして書かれているので、処理は重いです。今回のケースでは不要でしょう。
PHP Simple HTML DOM Parser
http://simplehtmldom.sourceforge.net/
PHP Simple HTML DOM Parserの使用方法
http://www.crystal-creation.com/web-appli/techni …
No.1
- 回答日時:
スクリプトからログインするためにWebページの取得と解析を行うことを「スクレイピング」と言い、検索するときに役立つので覚えておいてください。
以下に概要を示します。「$_GET」「$_POST」といったスーパーグローバル変数は出てきません。これらの変数を使うのはその「スクリプト」と「ユーザー」の間でパラメータを伴う通信を行う場合のみであり、これからその通信を行おうとしているのは「スクリプト」と「サイト」の間でのものです。1.
ログインフォームにGETでアクセスしてページ内容を取得する。多くの場合ではその中に不正アクセス対策のトークンが含まれている。この段階でサーバー側からCookieも送られてくる。
2.
ログインフォームに必要パラメータを添えてPOSTで送信する。必要パラメータは「不正アクセス対策のトークン」「ユーザーID」「パスワード」その他もろもろ。1で送信されてきたCookieを付加する必要がある。
3.
ログインが成功すれば、後は同じCookieを送信し続けるだけで会員専用ページなどの内容を取得することが出来る。
PHP言語を用いて「スクリプト」と「サイト」の間でHTTP通信を行う手段はいくつかあります。それを説明したいのですが…その前に、HTTP通信についての予備知識が必要なので以下のサイトの内容を先に把握しておいてください。全て分からなくてもいいのでおおまかに。
Studying HTTP
(かなり詳しいです)
http://www.studyinghttp.net/
とほほのWWW入門 - HTTP入門
(こちらの方がシンプルです)
http://www.tohoho-web.com/ex/http.htm
以下、関数などを紹介します。
● fsockopen関数・stream_socket_client関数
PHP Maual - fsockopen
https://php.net/manual/ja/function.fsockopen.php
PHP Manual - stream_socket_client
https://php.net/manual/ja/function.stream-socket …
PHPでHTTP通信を行うための最もローレベルな関数です。これらの関数は「スクリプト」と「サイト」の間で読み書き可能なストリームを確保します。
1. fwrite関数でリクエストヘッダーを送信(書き込む)
2. fgets関数・fread関数・stream_get_contents関数などでレスポンスを受け取る(読み込む)
PHP Manual - fwrite
http://php.net/manual/ja/function.fwrite.php
PHP Manual - fgets
http://php.net/manual/ja/function.fgets.php
PHP Manual - fread
http://php.net/manual/ja/function.fread.php
PHP Manual - stream_get_contents
http://php.net/manual/ja/function.stream_get_con …
最初から読み込めるわけではなく、必要な情報を送信して読み込めるようになるものであると思ってください。
● fopen関数
PHP Manual - fopen
https://php.net/manual/ja/function.fopen.php
php.iniの設定で「allow_url_fopen = On」になっている必要がありますが、実はファイルと同じようにサイトに対してもfopen関数でストリームを確保することが出来ます。リクエストヘッダー送信部分は先ほどのローレベルな関数と違って自動化されており、プログラマが記述するのは受け取る処理だけで済みます。自動化された部分を変更したい場合は、stream_context_create関数で「コンテキストリソース」というものを作成して、fopen関数の第4引数に渡す必要があります。CookieやPOSTデータを設定する場合はここをいじる必要がありますね。
PHP Manual - stream_context_create
http://php.net/manual/ja/function.stream-context …
PHP Manual - HTTPコンテキストオプション
http://php.net/manual/ja/context.http.php
● file_get_contents関数
PHP Manual - file_get_contents
http://php.net/manual/ja/function.file_get_conte …
「fopen + stream_get_contents + fclose」の一連の処理を一気に行い、文字列として返してくれる非常に優秀な関数です。こちらにコンテキストリソースを渡したい場合は第3引数に渡します。こちらも同様にphp.iniの設定で「allow_url_fopen = On」になっている必要があります。
● cURL関数群
Wikipedia - cURL
http://ja.wikipedia.org/wiki/CURL
PHP Manual - Client URL Library
http://php.net/manual/ja/book.curl.php
今まで紹介したものとは全く異なり、広く利用されている「cURL」というライブラリをPHPから利用する手段です。サーバーにcURLがインストールされていないと使用できないという欠点がありますが、実際は多くのレンタルサーバーで利用可能であり、パフォーマンス面でもこちらの方が優れているので利用価値は十分にあるでしょう。流れは以下のようになります。
1.
curl_init関数でcURLリソースを生成する。
2.
curl_setopt関数で必要なオプションを1つ1つ設定していく。またはcurl_setopt_array関数を利用して連想配列でまとめてオプションを設定する。設定できるオプションに関してはPHPマニュアルのcurl_setopt関数のページに全て記載されている。
3.
curl_exec関数でリクエストを実行する。デフォルトではレスポンスがそのまま出力されるが、オプションで「CURLOPT_RETURNTRANSFER」を有効にすることで、出力させずに文字列としてこの関数の返り値にすることが出来る。
先に紹介した3つの方法ではCookieが更新されるたびにコンテキストリソースに再セットし直す必要がありましたが、こちらはクッキーとして利用するファイルのパスを指定するので、最初に1回指定しておくだけで全てそれを使いまわすことが出来ます。・・・非常に便利な関数群なのですが、やはりそのままではこれでも使いにくいので、関数をラップしてクラス化したものを作ってみました。
Qiita - シリアライズ可能なcURLのラッパークラス
http://qiita.com/mpyw/items/c65fb4ec4cef80909a47
Cookieなどの情報に関して、serialize関数で保存・unserialize関数で復元できるように工夫しています。「クッキーファイル」を意識する必要が無くなっているので非常に使いやすいと思います。上の記事中にニコニコ動画スクレイピング用の継承クラスをサンプルとして掲載しているので参考にしてください。
なお、トークンをページから抽出する方法については、ここまでで回答が長すぎるので続きを書きます…
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(プログラミング・Web制作) Windowsのマクロプログラムで、こんなことできますか? 3 2022/06/28 14:30
- C言語・C++・C# チャットGPT 4について質問があります。 画像のような3つの種類がありますが、それぞれ何が違うので 1 2023/04/29 03:12
- 予備校・塾・家庭教師 塾 オンライン授業について 通っている塾にもう1教科プラスする事になり オンライン授業を始める事にな 1 2023/08/08 21:56
- Google Drive 【至急】Googleスプレッドシートについて教えて頂きたいです。 仕事で共有して作業を行うため取引先 3 2022/12/09 13:00
- ヤフオク! ヤフーアカウントについての質問です。 「不正利用が疑われる操作もしくは行為が検知されたため、利用規約 5 2022/08/29 20:22
- iPhone(アイフォーン) iPhone初期化について質問です。 親から使用時間や勝手にアプリをインストールできないように規制が 2 2022/08/21 11:52
- その他(セキュリティ) Facebookアカウントを乗っ取られ、ログインも出来ずパスワードの再設定もできずに困っている 2 2023/02/17 14:24
- Java 問題作成のWebアプリの作り方を教えてください 1 2022/11/26 22:01
- WordPress(ワードプレス) 「あるサイトのリンクを踏まないと、次のサイトを見れない仕組み」を作りたい 2 2022/07/20 02:43
- PHP ログインした掲示板ですが、直接開かないような設計するには? 2 2022/10/29 16:30
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
PHP ボタンが押されたら処理を...
-
フォームへの前回入力値をクリ...
-
検索時の選択内容を保持する方法
-
【PHP】 文字サイズの変更につ...
-
<input type="hidden" >で配列...
-
POST GET HTTP 404 未検出
-
テキストボックスとsubmitボタ...
-
画面が更新されてもチェックボ...
-
PHPの関数実行
-
input nameで日本語を使うと
-
PHP DBの登録情報をラジオボタ...
-
PHPでCookieを使った訪問回数に...
-
検索後にチェックボックスのON/...
-
syntax error, unexpected '}' ...
-
チェックボックスのvalueを連結...
-
PHPでユーザー情報を入力して簡...
-
チェックボックスを用い、MySQL...
-
PHPで画像の渡しが上手く行きま...
-
HTMLで前の画面に戻る時、入力...
-
フォームでのリセットを使う方法
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
<input type="hidden" >で配列...
-
検索時の選択内容を保持する方法
-
HTMLで前の画面に戻る時、入力...
-
DBの値をチェックボックスに反...
-
フォームへの前回入力値をクリ...
-
PHPでCookieを使った訪問回数に...
-
PHPで画像の渡しが上手く行きま...
-
PHP ボタンが押されたら処理を...
-
HTMLのリンクをクリックするこ...
-
syntax error, unexpected '}' ...
-
画面が更新されてもチェックボ...
-
チェックボックスのvalueを連結...
-
チェックボックスの必須項目指定
-
PHPでユーザー情報を入力して簡...
-
PHPの関数実行
-
POSTデータのNAME属性をVALUEに...
-
パラメーターを隠す
-
phpで分からないエラーが出てし...
-
PHPで、ボタンを押すと同じペー...
-
テキストボックスに初期値を入れる
おすすめ情報