phpでこのブログのRSSを取得しようとして、Feed.phpを読み込んでもにょもにょさせようとしたのですが、どうも上手く行かない。
Fatal error: Uncaught exception 'Exception' with message 'String could not be parsed as XML' in ... (略) ... SimpleXMLElement->__construct('<html><body><sc...', 96) ...(略)
と出てしまいます。
「あー、このRSSをXMLとしてパースすりゃあ良いんなー。待ってなー、こんなのホホイのホイで…って、これXMLじゃないやーんっ!(バシィッ」
ってノリツッコミしてるようです。
…そんな馬鹿な。
ちなみに走らせたPHPのコードはこんな感じ。
//フィード取得用ライブラリの読み込み require_once("./Feed.php"); $feed = new Feed; $url = "http://lab.ewigleere.net/rss_feed.xml"; $rss = $feed->loadRss($url); echo $rss->item[0]->title; //とりあえず最初のRSSのタイトルを出力(テスト用)
URLも間違っていないし、別のサイトだと成功するし。
最初は取得したxmlが上手く読み込めていないのが原因だと思い、文字コードとか改行コードとか確認していました。…文字コードもUTF-8、問題ない。改行コードも関係ない。
エラーメッセージ(String could not be parsed as XML とか)で検索するも、あまり情報がありません。検索結果の量は多いのですが、9割方は実際にそのエラーを発生させているページなので解決方法が書いてあるはずもなく。
これは困った。
ここでよくよくエラーメッセージを見直してみると、あることに気付きました。
SimpleXMLElement->__construct('<html><body><sc...', 96)
ん?「<html><body><sc...」?
なんでRSSのURL指定しているのにhtmlコード(しかもhtml→body→script(おそらくjs))が代入されているの?
何かがおかしいので実際のやり取りを見てみることに。コマンドプロンプト立ち上げて、telnetで接続。
telnet lab.ewigleere.net 80 GET /rss_feed.xml HTTP/1.1 User-Agent: Telnet [ja] (Windows) Host: lab.ewigleere.net HTTP/1.1 200 OK Server: XXXXXXXXXX Date: XXXXXXXXXXXXXXXXXXXXXX Content-Type: text/html Connection: keep-alive <html><body><script type="text/javascript" ...(後略
おー返ってきたなー…んんん?
予想通りといえば予想通りなのですが、htmlコード返してきましたよこの子。
確かにこれはXMLじゃないですね。見て分かります。
…問題はそこではなくてですね。何故にhtmlコードを返してきているのかと。
で、よくよくソースを見てみると、どうもこれはjavascriptでAESの暗号化をしているようです。
その上でlocation.hrefして本来のURLにリダイレクトしている模様。
仕方ないのでWireSharkでその一部始終を追ってみると、確かに302 Foundでリダイレクトしている。
ついでに、処理を終えるとGETパラメータ(?ckattempt=1)を付与していますね。ちなみにこのパラメータをくっつけても(PHP、telnet共に)変化はありませんでした。たぶんその後の処理でcookieを付けているっぽいので、そのcookieを提示しないとリダイレクト先には行けないような感じ?
…最近アクセスすると謎のGETパラメータがくっ付いてくるなー、と思ったら…これが原因か。
javascriptのファイル名を信じるならばこれはAESの処理のはずなので、セキュリティの絡みっぽいですが…これは困った。
feedlyなどのRSSリーダーもhtmlソースを返されるものだから最新の記事を表示してくれないし…。やるならjavascriptではなくてPHPとかでやってくれれば、こういうことにはならないと思うのですが…。
$ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_POSTREDIR, 2); //2 = 302 Found curl_setopt($ch, CURLOPT_MAXREDIRS, 3); $tmp = curl_exec($ch); curl_close($ch); var_dump(htmlspecialchars($tmp));
上記を参考にcUrlで取得しようと試みましたが失敗。そもそも、上記の場合はhtaccessとかPHPとか、HTTPレスポンスヘッダにlocationの値がある場合に作用するのであって、ドキュメントを取得した後に、そこに記述されているjavascriptでリダイレクトしている場合は意味がない。上記の推測が正しかった場合、cookieも考慮しないといけないわけですし。
ということで、現状打開策が見付からず。
困った困った…。