質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

2回答

1491閲覧

スクレイピングできない要素をいかにして取得するか?

GiantGiny

総合スコア12

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

1グッド

2クリップ

投稿2019/03/15 16:53

前提・実現したいこと

phpQueryでスクレイピングシステムを作っています。
あるミュージックサイト(Spotify)でのみ要素が取得できないエラーが発生しました。

発生している問題

Spotifyでアルバムのタイトルを取得しようとしているのですが、下記のソースコードで何もechoされない状態です。

該当のソースコード

こちらが該当のソースコードになります。

明らかにこのアルバムのページ(https://open.spotify.com/album/7IBlkWr9DvKRWyR5RSrRcm?si=mtJmYWxJQRCY9VW6cO0GVw)に「.tracklist-name」というクラスは1つしかなく、それについて「eq(0)」で取得しているはずなのですが、echoされません。

PHP

1<?php 2require dirname(__FILE__) . '/phpQuery-onefile.php'; 3$url='https://open.spotify.com/album/7IBlkWr9DvKRWyR5RSrRcm?si=mtJmYWxJQRCY9VW6cO0GVw'; 4$html = file_get_contents($url); 5$doc = phpQuery::newDocument($html); 6echo $doc[".tracklist-name:eq(0)"]->text()."\n"; 7?>

次のように3つ試しましたところ、不思議な状態です。

試したこと

まず次のように「.tracklist-name」を詳細に指定してもechoされません。

PHP

1echo $doc["#main > div > div.Root__top-container.Root__top-container--has-notice-bar > div.Root__main-view.Root__main-view--has-upsell-bar > div > div > div > section > div > div > div.col-xs-12.col-lg-9.col-xl-8 > section > ol > div > div > li > div.tracklist-col.name > div > div.tracklist-name.ellipsis-one-line"]->text()."\n"; 2

一方次のようにtitleタグを指定すると、正常に「Goodbye Kisses by Joe Hertz on Spotify 」がechoできました。

PHP

1echo $doc["title"]->text()."\n";

そして次のようにh2タグを指定すると、なぜか「By Joe Hertz」という値(開発ツールで見ても存在しない値)がechoされました。

PHP

1// 2echo $doc["h2"]->text()."\n";

以上3つを試しましたが問題の原因が皆目つかめず、困り果てております。

具体的な解決策や試すべき事柄についてご存知の方がもしいらっしゃいましたらどうかご教授願えませんでしょうか。

宜しくお願い致します。

ツールのバージョン

●phpQuery 0.9.5

・公式サイト
https://code.google.com/archive/p/phpquery/downloads

・ダウンロードリンク
https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/phpquery/phpQuery-0.9.5.386-onefile.zip

oppeke👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

Spotify 利用規約、9章のとこに

  1. Spotify サービスの “クローリング” またはそれ以外で自動化手段を利用して Spotify または Spotify サービスの情報を表示し、これにアクセスし、またはこれを収集すること (ボット、スクレイパーおよびスパイダーを含みます。)。

ってかかれてますけど、だいじょーぶ?

投稿2019/03/15 23:22

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2019/03/15 23:23

勝手にやったらアウトですね。
退会済みユーザー

退会済みユーザー

2019/03/15 23:27 編集

そうですねー ま、どーせこの質問者のアカウントはサブ垢かなんかでしょw 回答分の+2ポイント、ごちそうさまでしたってカンジー
GiantGiny

2019/03/16 06:45

どもです。APIあったみたいです。
guest

0

ベストアンサー

chromeのxhrタブを見ると、それっぽいのがあります

xhrtab

んでまずリクエストを手元の端末でcurlとかでエミュレートする
右クリでcopy as cURL , winだったらcopy as powershell
chrome
そしたら
こんな感じのリクエストが取得できる

curl "https://api.spotify.com/v1/albums/7IBlkWr9DvKRWyR5RSrRcm?market=JP" -H "Accept: application/json" -H "Referer: https://open.spotify.com/album/7IBlkWr9DvKRWyR5RSrRcm?si=mtJmYWxJQRCY9VW6cO0GVw" -H "Origin: https://open.spotify.com" -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36" -H "Accept-Language: ja" -H "Authorization: Bearer ..." --compressed

ミソはAuthorizationでこいつがないと弾かれる。ゲストトークンなら固有値なのでそのままスクレイピングするスクリプトにぶちこめばいい

追記:APIがあるのでスクレイピングせずこちらを使いましょう。
https://qiita.com/musiccoffeetea/items/69a58d6d66e42b3c113f
https://developer.spotify.com/documentation/

投稿2019/03/16 00:07

編集2019/03/16 02:32
39ff

総合スコア284

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/03/16 00:15

わー!ゆずちゃんやさしー!
39ff

2019/03/16 02:28

普通にMusic Metadata APIで取れますね(汗
GiantGiny

2019/03/16 06:42

b2759さん、ありがとうございます。仰る通りAPIが良さそうですね。汗 APIだと例えばこれ「https://open.spotify.com/album/1xf8Ny57YgeCJxNKm2oVDd?si=y3FMZ6kxRiO497SvpJKWiA」は取れるんですが、 これ「https://open.spotify.com/user/spotify/playlist/37i9dQZF1DWVqfgj8NZEp1?si=-T1nwM6dSzGL1K9WHCYk4w」が取れなくないですか? どうやら「album」は取れるけど「playlist」だと取れないのかな?b2759さんはできましたか?
GiantGiny

2019/03/16 07:56 編集

あれ、すみません。そもそも良く分かっておりませんんでした。 下記のコードを考えてみたのですが、そもそもどこにアクセストークンとかを入れればいいのでしょうか? http://codepad.org/WQeUOGJz (こちらのコメント欄に書くとダブルクオートがおかしいので、codepadに置いておきました。) 上では「トークンありませんよ」となってしまいまして、、 ちなみに、すでにダッシュぼーどにはログインでき、「Client ID」と「Client Secret」は持っています。
m.ts10806

2019/03/16 08:29

コメント欄ではマークダウンは使えません。 質問本文修正されては
39ff

2019/03/16 09:50

$headers = [ 'Authorization: Bearer xxx' ]; curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); こんな感じ。 でもこれ、searchエンドポイントでは情報取得できなくないですか?
GiantGiny

2019/03/16 10:04 編集

すみませんニアミスでしたね。僕の上のcodepadですと、何かのjsonは取得できてはいるんですが(なんだこれ?w)、でもプレイリストのタイトルとか、肝心なデータがないように思います。 う”う”う”う”…限界です。上のcodepadをb2759さん流で正しく直してもらえませんでしょうか。
39ff

2019/03/16 10:07

後ほど回答します
GiantGiny

2019/03/16 10:11

失礼致しました。また入れ違いでした。「後ほど」とのこと。ありがとうございます。週末のお忙しい中すみません。お待ちしております。
GiantGiny

2019/03/16 10:26 編集

ありがとうございます。 そしたら、こうですよね? https://paiza.io/projects/ncP_EHnx4W0jcAkviPDrUQ んーーー!??どうして上でできないのでしょうか? spotifyのサイトで試したのでトークンは有効なはずなのです。 プレイリストの URL を Get として$headersの中に入れたみただけではできないのでしょうか?
39ff

2019/03/16 10:35

できないというのは、エラーが返るということでしょうか?
39ff

2019/03/16 10:41 編集

確認ですが https://api.spotify.com/v1/playlists/37i9dQZF1DWVqfgj8NZEp1 をリクエストしたときに返るレスポンスは次のようなものです https://gist.githubusercontent.com/39ff/d2b2f70de8064b2290678b7da6fff7d2/raw/5fdeecc5d6eac0468ea7f376cb2062ce79bac692/playlist1.json https://api.spotify.com/v1/playlists/37i9dQZF1DWVqfgj8NZEp1/tracks にリクエストしたときに返るレスポンスは次のようなものです https://gist.githubusercontent.com/39ff/d2b2f70de8064b2290678b7da6fff7d2/raw/5fdeecc5d6eac0468ea7f376cb2062ce79bac692/track.json この2つのデータに必要としているデータはありますか?
GiantGiny

2019/03/16 11:14 編集

>19:35 エラーはなく、<pre></pre>としかechoされません。 こちらです↓。トークンつきでご覧くださいませ。 https://...【トークンつきは不適切なのでこの部分は削除しました】 このような状況です。 >19:39 はい、前者にあります。「Relax to the sound of jazz」(つまりプレイリストのタイトル)が必要です。画像と作成者の情報も欲しいですが、それも前者にあるようです。paizaのコードで前者のようなjsonが取得できないのはなぜなのでしょう…
39ff

2019/03/16 10:53

トークン付きで掲載されていますがセキュリティ上問題あるので削除依頼してください
GiantGiny

2019/03/16 11:22 編集

なるほどjsonの全てではなく、descriptionとnameを指定してくれたわけですね。すると、 Notice: Undefined property: stdClass::$description Notice: Undefined property: stdClass::$name というエラーが出てしまいました… あとは「file_put_contents」の行にもにもエラーありのようです。
GiantGiny

2019/03/16 11:23 編集

すみません! 上のエラーですが、トークンの有効期限が切れたみたいで、そもそもjsonが取得できてなかったためのようでした。 トークンを再発行したところ、きちんと「Relax to the sound of jazz」が出力されました。 どうもありがとうございます。 あとは「file_put_contents」の行のエラーですが、こちらの行は消しちゃっても大丈夫ですよね? でもこれ、トークンに有効期限なんてあるんですね…使いづらい…笑
GiantGiny

2019/03/16 11:38

なるほど。 トークンはあらかじめ $access = 'x'; と性的に書いておくのではなくて、 $access = 自動更新されたトークン; と動的に取得する方法があるわけですね。 ありがとうございます。じっくりググってみます。 何度もありがとうございました。英語がてんてこまいすぎて本当に困っていました。心から感謝です。
GiantGiny

2019/03/21 17:53 編集

b2759さん、こんにちは。 あれからトークンの発行もできました。 https://...【トークンつきは不適切なのでこの部分は削除しました】 そこでお聞きしたいのですが、b2759さんのような方(おそらくその道の専門家の方)のお考えとして、上記のように「毎回トークンを発行する」のは、イケてないでしょうか? Spotifyのトークンは「1時間ごと」の間隔で自動更新されるのですが、上記ではその間隔に関わらず「とにかく毎回」発行するようになっています。 この仕様について、b2759さんはいかが思われますでしょうか? またもしイケてないとしたら、どのように変更されますか? よろしければご意見をお聞かせいただきたくコメントさせて頂きました。 もしお時間ございましたら、ご返答お待ちしています。
39ff

2019/03/19 03:33

OAuth2.0のAPIで普通はaccess tokenの有効期限が切れている場合にrefresh tokenを用いて新しいトークンを取得するというロジックを入れると思います
m.ts10806

2019/03/19 03:35

要件追加されすぎてるように思います。要件は質問本文に追記してください。
GiantGiny

2019/03/21 17:55

b2759さん、やはりそうですよね。ありがとうございます。 ただ、既存トークンの期限が切れているかどうかの判別とは例えばどのようなコードになりますでしょうか? 既存トークンがもし切れていたときそれはすでに使えず、よって期限切れかどうかさえ判別できないように思うのですが…
39ff

2019/03/22 05:18

>expires_in int The time period (in seconds) for which the access token is valid. 取得した時間からexpires_in秒使えるということなので <?php //例 $expire_in = 3600 - 60; $expire_timestamp = strtotime('+'.$expire_in.' sec' ,time()); var_dump($expire_timestamp); if($expire_timestamp < time()){ //期限切れなのでupdate処理 } とか。 エラーが出た段階でrefresh_tokenで新しくトークンを取得をトライして、それでもダメならユーザに再認証させるというロジックでも良いと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問