Rubyによるアメブロ『いいね』自動化スクリプト(3) 「いいね」のターゲット設定(その1)
前回までで、「いいね」をつけるスクリプトが出来たので、今回はそのターゲットの抽出方法。
依頼者の要望は、
「自分のブログ記事についた「いいね」をお返しする」
と言うこと。
なので、自分のブログ記事についた「いいね」を取得する方法を考える。
「いいね」のデータを取得するには大きく3つの方法がある。
(1)記事のいいねのリンクから、その記事についた「いいね」を新しい順に見ることができる。
(2)ログインした状態の「いいね」履歴で
(2)-1 記事毎についた「いいね」の履歴を見ることができる。記事は記事の日付時刻順ではなく、「いいね」がついた時刻の新しい順に整列される。だから大昔の記事でも「いいね」が新しくつけば、データの先頭になる。
(2)-2 「いいね」をつけてくれたユーザ毎のデータを取得できる。この時もユーザの並びは「いいね」をつけた時刻の降順。新しく「いいね」をつけてくれたユーザほど新しく表示される。
これらのいずれの場合でも、データはhtmlではなくjsonの形式で送られて来る。一回のリクエストではデータ10件のみが送られ、全件のデータを得ることは出来ない。
この一度に全件データが得られないとこら辺が、自動処理が面倒になる所なのだが、自動処理はサービス供給側の意図から外れているし、全件データ送信はトラフィックとサーバーの負荷がやたらに増えて仕方ないので妥当な処理方法という所か。(そもそも今回のシステム変更の目的が、トラフィックとサーバー負荷の低減だったのではないかという気もする)
依頼者の要求仕様のお返しとしての「いいね」をつける相手に合致するのは、単純に「いいね」時刻順でデータを得られる(3)の方法。
この(3)の場合に送られてくるデータの内容を、もう少し詳しく見る。
データを得るためのリンクを押すと以下のリクエストが送られる。
GET /api/iine_history_user.json ?ts=1389608323904&callback=iineHistoryUserCallback&_=1389608323908 HTTP/1.1 Host iine.blog.ameba.jp User-Agent Mozilla/5.0 (Windows NT 6.0; Win64; x64; rv:29.0) Gecko/20100101 Firefox/29.0 Referer http://blog.ameba.jp/ucs/iine/list.html
ここで"ts"、および"_"というデータは、リクエストが発生した日時をGMTの1970年1月1日午前0時からの経過秒数でシリアライズされたモノ。
(どちらか片方だけで良い様な気がするのだが…)
リクエストの中には、自分のブログを表わす情報が全く入っていない。おそらく、そこら辺はクッキーで処理されているのではないかと想像しているのだが、良く分らない。
以下が送られてくるjsonのデータ例。
iineHistoryUserCallback({ "successFlg": true, "lastUpdMillis": 1389364094206, "lastFlg": false, "userList": [{//1件目のデータ "validFlg": true, "amebaId": "*****", "blogTitle": "************", "iineCount": 1, "profile": { "nickname": "***", "profileImage": { "url": "http://stat.profile.ameba.jp/profile_images/******/**.jpg", "height": 2048, "width": 1536 } } }, // ...途中省略... {//10件目のデータ "validFlg": true, "amebaId": "****", "blogTitle": "*******", "iineCount": 4, "profile": { "nickname": "****", "profileImage": { "url": "http://stat.profile.ameba.jp/profile_images/**************/**/****.jpg", "height": 236, "width": 243 } } }] });
送られてくるデータは、整形されていないベタのテキストデータだが、http://jsbeautifier.org/で整形。
内容を見ると
"lastUpdMillis"という項目に 1389364094206という数値が入っている。(この項目については後述)
"lastFlg"という項目に falseが入っていて、リストがまだ続く事がわかる。
"userList"の項目は、「いいね」をつけてくれた相手のid、相手のブログタイトル、「いいね」をつけてくれた回数、相手のプロファイルデータが10件分入っている。
"lastUpdMillis"という項目は、どうもこの10件の次、つまり11件目以降の「いいね」をつけてくれたユーザーのデータをリクエストする時に必要なデータで、10件目がついた日時データの様な気がする。(もしかしたらサーバー側が11件目の日時データを返して来ているのかも知れないが…)
でこの次のデータをリクエストする場合には、
GET /api/iine_history_user.json?updMillis=1389364094206 &ts=1389614304062&callback=iineHistoryUserCallback&_=1389614304064 HTTP/1.1
と、"lastUpdMillis"のデータを追加して送る。
このリクエストを"lastUpdMillis"の値が自分が望む日時になるまで、或いは"lastFlg"がTRUEになるまで繰り返して、データを得れば良い。。
Rubyによるアメブロ『いいね』自動化スクリプト(2) 『いいね』をつけるスクリプト
1回目で説明した「いいね」をつける仕組みをrubyで実装する。
まずはアメブロにログインしてクッキーを入手するスクリプト
require 'digest/md5' require 'net/http' Net::HTTP.version_1_2 cookie = Hash.new #Set-Cookie def set_cookie_from_res(res,cook) if not res.get_fields('Set-cookie') == nil res.get_fields('Set-cookie').each{|str| k,v = str[0...str.index(';')].split('=') cook[k] = v } end end def cookie_str(cook) cook.map{|k,v| "#{k}=#{v}" }.join(';') end #Program Start print "Please input your BlogID :" blog_id = gets.chop print "Please input your password :" blog_pwd = gets.chop print "Please input iineNo :" iine_no = gets.chop.to_i #ログインしてクッキーを入手 http = Net::HTTP.new("www.ameba.jp",80) path = '/' req=Net::HTTP::Get.new(path) req['Connection'] = 'Keep-Alive' req['Cookie'] = cookie_str(cookie) req['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.0; Win64; x64; rv:29.0) Gecko/20100101 Firefox/29.0' http.start response = http.request(req) set_cookie_from_res(response,cookie) path = '/login.do' post_data = 'amebaId=' + blog_id + '&password=' + Digest::MD5.hexdigest(blog_pwd) + '&Submit.x=0&Submit.y=0' req = Net::HTTP::Post.new(path) req['Connection'] = 'Keep-Alive' req['Cookie'] = cookie_str(cookie) req['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.0; Win64; x64; rv:29.0) Gecko/20100101 Firefox/29.0' response = http.request(req,post_data) if response.code == '302' set_cookie_from_res(response,cookie) #ここに「いいね」をつけるスクリプトを書く else print "Wrong ID or wrong pathword!!" end
このスクリプトは前のペタ貼りのスクリプトと同じ。
ユーザエージェントの設定は、素直にrubyのままだとサーバー側で弾かれるかも知れないのでFireFoxを詐称している。(アメブロさん、ごめんなさい)
上記のスクリプトの『#ここに「いいね」をつけるスクリプトを書く』の部分に、コードを入れる。
まずは、準備として、
(1)「いいね」をつけたいアメブロのidが入っている配列
(2)サーバーから受け取った文字列からデータを抽出するための正規表現
を定義する。
iine_list = Array.new#「いいね」つけたいidを入れる配列 iine_entry_url = Regexp.new("/web/display_iine.html\\?receiveAmebaId=[A-Za-z0-9\-] +&entryId=[0-9]+&from=entry&device=pc")#いいねボタン検出 iine_receiveAmebaId = Regexp.new('name="receiveAmebaId" value="[A-Za-z0-9\\-]+"') iine_entryId = Regexp.new('name="entryId" value="[0-9]+"') iine_token = Regexp.new('name="token" value="[a-z0-9]+"')
前回の「いいね」のしくみで調べたように、「いいね」の管理は一般的のアメブロの記事と別サーバーなので、スクリプトではhttp2を用意して、「いいね」のサーバーを割り当てる。
「いいね」をつけるスクリプトのコードは以下の通り
http2 = Net::HTTP.new("iine.blog.ameba.jp",80) iine_list.each do |line| begin print "Checking ", line ," blog... " target_blog_path = '/' + line + '/' response = http.get(target_blog_path,header) set_cookie_from_res(response,cookie) if response.code == '404' print "Can't find target blog." else iine_entry = iine_entry_url.match(response.body).to_s path = iine_entry+' HTTP/1.1' header['Referer'] = 'http://ameblo.jp'+target_blog_path response = http2.get(path,header) if response.body =~ /alreadyIineFlg:true/ print "Already iine" else receiveAmebaId = iine_receiveAmebaId.match(response.body).to_s.sub (/name="receiveAmebaId" value=/,'').tr('"','') if not receiveAmebaId == '' entryId = iine_entryId.match(response.body).to_s.sub (/name="entryId" value=/,'').tr('"','') token = iine_token.match(response.body).to_s.sub (/name="token" value=/,'').tr('"','') postdata = 'receiveAmebaId=' + receiveAmebaId + '&entryId=' + entryId + '&token=' + token + '&from=entry&device=pc' print "Sending iine..." path = '/web/exec_iine.html HTTP/1.1' header['Referer'] = 'http://iine.blog.ameba.jp/web/display_iine.html?receiveAmebaId=' + receiveAmebaId + '&entryId=' + entryId + '&from=entry&device=pc' response = http2.post(path,postdata,header) print "OK" else print "No iine_entry in this blog." end end end rescue Timeout::Error print "Timeout!!" rescue Errno:: ECONNRESET print "Econn reset!!" ensure print "\n" end end
さて、問題はiine_listの中に入れるアメブロのid。
ターゲットになるidをどうやって取得するのか…
次回は、その取得方法について書く。
Rubyによるアメブロ『いいね』自動化スクリプト(1) 『いいね』のしくみ
アメブロが11/20にシステム変更を実施した。
『ペタ』の代わりにフェイスブックもどきの『いいね』というボタンを押すしくみになった。
(アメブロの中には、フェイスブックの「いいね」ボタンもあるから話がややこしい…)
運営側がどういう意図でシステムの変更を行ったのかは判らないが、スクリプトを書いて『ペタ』貼りを自動化していた利用者としては、今回の『いいね』も自動化したくなる。
ペタの自動化スクリプト製作依頼のあった件の知り合いから、今度は『いいね』の自動化スクリプト製作依頼が来る。
ペタの時同様に、そうやって無駄にネットワークのトラフィックを増やして虚勢を張らなくても良いだろうと言ったのだが、当人にはそういう事がとても大事な様で、どうしてもと頼み込まれた。
と言うわけで、この『いいね』を自動化するスクリプトを作成する。
FireFoxのアドインHttpfoxを使って、『いいね』ボタンの表示、ボタンを押した時にブラウザとサーバーの間でどんなやりとりをしているのかを調べる。
「いいね」ボタンの表示
「いいね」ボタンHTMLの下記の様に、インラインフレームを利用して読み込まれる。
<iframe src="http://iine.blog.ameba.jp/web/display_iine.html? receiveAmebaId=****(ブログid) &entryId=**********(ブログ記事id 11桁の数値) &from=entry&device=pc" name="iine" class="iineBtnIframe" allowtransparency="true" frameborder="0" height="34" width="100%">いいね!</iframe>
「いいね」ボタンの詳細データを入手
上のアドレスからデータをGETして、「いいね」ボタンの詳細データを入手する。
Host iine.blog.ameba.jp GET /web/display_iine.html? receiveAmebaId=**** &entryId=*********** &from=entry &device=pc HTTP/1.1
この時、大事なのは、
(1)リクエストヘッダーのRefererに"http://ameblo.jp/****/entry-***********.html"を入れておく事。
これを入れておかないと、データが帰ってこない。自動化スクリプト対策(?)でサーバー側でGETリクエストとリクエストヘッダーのRefererをチェックしているのだろうと考えられる。
(2)予めログインしてクッキーを入手、一緒に送信する事。
クッキーでSession-id等をサーバーに送らないと、サーバー側では誰が「いいね」をしようとしているのか判らない。(ログインとクッキーについては過去記事参照)
このリクエストの結果、下記のHTMLが得られる。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <link media="screen,print" rel="stylesheet" href="http://stat.ameba.jp/blog/css/user/blogIineBtn.1.000.css"> </head> <body> <div id="iineBtnFrame"> <form action="http://iine.blog.ameba.jp/web/exec_iine.html" method="post" id="iineForm"> <input type="hidden" name="receiveAmebaId" value="****" id="receiveAmebaId"> <--****はブログのid --> <input type="hidden" name="entryId" value="**********" id="entryId"> <-- 記事のid 11桁の数字 --> <input type="hidden" name="token" value="********************************"> <--トークン:数字とアルファベット小文字32文字の組み合わせ--> <input type="hidden" name="from" value="entry"> <input type="hidden" name="device" value="pc"> <div id="iineBtnContent"> <p id="iineBtn" class="alreadyIine iine"><span>いいね!</span></p> <p id="iineBtnerror"><span>いいね!</span></p> <p id="iineCount" class=""> <span class="iineCountContent"> <span id="connected"></span> <span id="disconnected">4</span> </span> <span class="iineCountFrame"></span> </p> </div> </form> </div> <script src="http://stat.ameba.jp/blog/js/user/iineBtn.js"></script> <script> new Amb.IineBtnAmb.PcBlog({ setting:{ loginFlg:true, alreadyIineFlg:false, iineEntryTotalCount:4, receiveAmebaId:'****', eid:'***********', from:'entry', blogDomain:'http://blog.ameba.jp', iineDomain:'http://iine.blog.ameba.jp' } }); </script> </body> </html>
を得られる。要点は
(1)32桁のトークン
<input type="hidden" name="token" value="********************************">
(2)javascriptの中に記述されている
alreadyIineFlg:false
の部分。
トークンは、良いねボタンを押した時にサーバーに送るpostの中に含める必要がある。
'alreadyIineFlg'は、その記事の「いいね」をサーバに送ってなければ'false'、既に送っていれば'true'になる。「いいね」は、既に「いいね」を送った記事に対して、再度postを送信した場合には「いいね」が取り消しになる仕組み。粗っぽい自動化スクリプトを作って、この'alreadyIineFlg'を確認せずに、重複してpostを送った場合には、せっかく過去につけた「いいね」が取り消しになってしまう。
記事に「いいね」をつける
記事に「いいね」をつけるためには、上記で得られたサーバーに下記の様にデータをPOSTする。
サーバーとポスト先のパスは
Host iine.blog.ameba.jp POST /web/exec_iine.html HTTP/1.1
ここでもヘッダーにRefererをつけるのを忘れてはいけない
Referer http://iine.blog.ameba.jp/web/display_iine.html? receiveAmebaId=****&entryId=***********&from=entry&device=pc
POSTするデータは以下の通り
receiveAmebaId **** entryId *********** token ******************************** from entry device pc
以上の一連のやりとりによって、目標の記事に「いいね」をつける事ができる。
ライブラリ
Delphiから長く離れていたのと、元々VCLの理解が浅いので、Delphiの勘を取り戻すのに四苦八苦している。
サンデープログラマがプログラムを組む場合、構想(アーキテクチャ)に費やす時間は短い。どちらかと言うと、実装(インプリメント)に時間がかかる。
そりゃそうだ。
サンデープログラマの場合、プログラムをいじり始めた時点で、構想部分は日々の生活の中で頭の中に十分にできあがっている。売れるか否かとか心配する必要はないし、構想に対して注文や文句をつける上司もいない。僕の様な、ソフトウェアを生業としていないサンデープログラマが苦労するのは、構想を如何に実現するかの実装部分だ。30年前ならは、データ構造とアルゴリズムを決めて、ゴリゴリとプログラムを組めば良かった。今でも、スクリプトとかはそう言う組み方だ。
しかし、GUIとかマルチメディアが入ってきて、プログラムを対話的(イベントドリブン)に扱わないといけなくなってから、一気にハードルが上がった。OSが提供するそういう機能をラップするために、各開発言語/環境でライブラリが提供され、ちょっと気の利いたソフトを作ろうと思ったら、そのライブラリを誤魔化しながらでも使う程度には理解する必要が出てきた。ボーランド系の開発環境ならOWL、VCL、CLX…、そして今はWindowsとMac/iOSまでクロスで開発できるFireMonkeyなんていうのまである。
本当はそのクロスプラットフォームのFireMonkey辺りを勉強し直せば良いのかも知れないのだけど、PC・スマホ・タブレット・携帯プレーヤーまで含め未だにアップル製品とは縁がない生活。それなら慣れ親しんだWindows用のVCLで良いか…というのが現在の判断。まぁ、実際はタブレットやスマホと縁がないから、タッチパネルでの操作体系が分からないだけ…
と言う訳で、ここ暫くはこのブログ、VCLのお勉強とメモが続くだろう。
しかし、こうしたライブラリの内容を説明した日本語の資料が少ない。
10年ほど前に出たDelphiの文献、特に難しそうなのを、少し高いなぁと思いながら当時買っておいて良かったなぁ…と思っている。
Marco Cantuの本とか、オライリーから出た山猫が表紙の本、中村拓男『Delphi コンポーネント設計&開発完全解説』、堀越一雄『Delphi オブジェクト指向プログラミング』とかね。
C++とかで開発されている人はどうしているのだろう?
使ってるライブラリの資料は手に入ってるのかしら
Rubyによるアメブロのペタ貼り自動化スクリプト(16) まとめ
いささか不具合があるものの、一旦、改善したスクリプトをココに貼って、一区切り。
クライアントからは、『Androidスマートフォンから同様の事が出来る様にしてくれ』というワガママな依頼が来ている。
AndroidはJavaのサブセットだから、アルゴリズムが決まっていれば、Rubyでなくても簡単にできそうな気がするけれど、僕自身がAndroidの実行環境を持っていないので、いささか敷居が高い。
ボチボチとJavaの復習と、Androidの勉強をしようかと考えている所。
以下、暫定の最終コード
require 'csv' require 'digest/md5' require 'net/http' Net::HTTP.version_1_2 #おまじない cookie = Hash.new #Set-Cookie→クッキーの設定 def set_cookie_from_res(res,cook) res.get_fields('Set-cookie').each{|str| k,v = str[0...str.index(';')].split('=') cook[k] = v } end def cookie_str(cook) cook.map{|k,v| "#{k}=#{v}" }.join(';') end list = Array.new not_list = Array.new ameba_url = Regexp.new("http:\/\/ameblo.jp\/([A-Za-z0-9]*)\/") peta_url = Regexp.new("(?-mix:\\/p\\/addPetaComplete.do(?:\\?(?:[;\\/?:@&=+$,A-Za-z0-9\\-_.!~*'()]|%[0-9a-fA-F][0-9a-fA-F])*))") peta_entry = Regexp.new("/p/addPeta\\.do\\?targetAmebaId=[A-Za-z0-9\\-]+&service=blog_e&key=[0-9]+&sig=[a-z0-9]+") amember_entry = Regexp.new("secret.ameba.jp/[A-Za-z0-9\\-]+/amemberentry-[0-9]+.html") print "Please input your BlogID :" blog_id = gets.chop print "Please input your password :" blog_pwd = gets.chop #まずwww.ameba.jp/に接続してセッションIDを入手する http = Net::HTTP.new("www.ameba.jp",80) path = '/' req=Net::HTTP::Get.new(path) req['Connection'] = 'Keep-Alive' req['Cookie'] = cookie_str(cookie) http.start response = http.request(req) set_cookie_from_res(response,cookie)#入手したクッキーからセッションID等をハッシュに設定する #ID、パスワードを送信して、ログインする path = '/login.do' post_data = 'amebaId=' + blog_id + '&password=' + Digest::MD5.hexdigest(blog_pwd) + '&Submit.x=0&Submit.y=0' req = Net::HTTP::Post.new(path) req['Connection'] = 'Keep-Alive' req['Cookie'] = cookie_str(cookie) response = http.request(req,post_data) if response.code == '302' set_cookie_from_res(response,cookie)#入手したクッキーからpetaに必要なクッキーをハッシュに設定する #設定されたペタターゲットファイルを読み込む print "Reading Target textfile...\n" File.open("peta_target.txt").each do |file| file.each_line do |line| list.push(line.chomp!) end end #ペタをつけないブログのリストを読み込む print"Reading NG Blogs datafile...\n" File.open("peta_not_list.txt").each do |file| file.each_line do |line| not_list.push(line.chomp!) end end #自分のブログについたペタを確認。ペタ返しのためのブログurlをリストに追加する。 print "Reading Recieved Petadata...\n" for i in 1..25 res = Net::HTTP.get('peta.ameba.jp','/p/addPeta.do?petaId=&targetAmebaId='+blog_id+'&pageNo='+i.to_s) res.to_s.scan(ameba_url) do |a| list.push(a[0]) end end #自分のつけたい分野のランキングを確認。例)本、読書ランキング上位のブログ for i in 1..10 res = Net::HTTP.get('ranking.ameba.jp','/genre/detail?genreCode=book&page='+i.to_s) res.to_s.scan(ameba_url) do |a| list.push(a[0]) end end #この後に更に自分のつけたい分野のランキングがあるならば上記を同様に繰り返すを確認 list.delete(blog_id)#自分のブログを外す list.delete("famousblog")#人気ブログへのリンクを外す list.delete("content")#プレミアムブログへのリンクを外す list1 = list.uniq list1 = list1 - not_list#ペタをつけない設定のブログを外す #ログデータのlogへの読み込み log = Array.new log = CSV.readlines('logdata.csv') #各ペタページにアクセスしてペタ貼りをする http3 = Net::HTTP.new('peta.ameba.jp',80) http3.start header = Hash::new header['Connection'] = 'Keep-Alive' header['Cookie'] = cookie_str(cookie) g = 0 ng = 0 nup = 0 list1.each do |line| print "Checking ", line ," blog... " #Get peta_entry url response = Net::HTTP.get('ameblo.jp','/'+line+'/') if peta_blog_e_get = peta_entry.match(response) entry_point = peta_blog_e_get.begin(0) peta_e_log = peta_blog_e_get.to_s #serchi Amenber entry #if find amenber entry link, check position between peta_link if (amember_e_get = amember_entry.match(response)) and (entry_point > amember_e_get.begin(0)) amember_path = amember_e_get.to_s amember_path.sub!(/secret.ameba.jp/,'') http2 = Net::HTTP.new('secret.ameba.jp') http2.start amember_response = http2.get(amember_path, header) http2.finish if peta_entry.match(amember_response.body) peta_e_path = peta_blog_e_get.to_s posting_text = "from blog entry(amenber).." else peta_e_path = '/p/addPeta.do?targetAmebaId='+line+'&service=profile' posting_text = "from Profile(not amenber)..." end else peta_e_path = peta_blog_e_get.to_s posting_text = "from blog entry..." end if (log.assoc(line) == nil) or (log.assoc(line)[1] != peta_e_log) then print "Posting Peta " + posting_text response = http3.get(peta_e_path,header) if petaIDget =peta_url.match(response.body) peta_path = petaIDget.to_s response = http3.get(peta_path,header) if log.assoc(line) == nil then log << [line, peta_e_log] else log.assoc(line)[1] = peta_e_log end print "OK" g += 1 else print "NG" ng += 1 end else print "not updated." nup += 1 end else print "can't find peta link." end print "\n" end http3.finish print "\n" print "Number of peta target blogs: ", list1.length, "\n" print "Post peta successed: ", g, "\n" print "Post peta faild: ",ng, "\n" print "Not updated blogs: ", nup, "\n" #ログデータの書き込み print "\n" print "Saving log data. Wait a moment..." CSV.open("logdata.csv", 'w') do |writer| print "finish!\n" log.each do |line| writer << line end end else print "Wrong ID or wrong pathword!!" end http.finish
Rubyによるアメブロのペタ貼り自動化スクリプト(15) アメンバー限定記事の処理の不具合
前回までにアメンバー限定記事の処理コードを書いた。
のだけれども、どうもまだ不具合がある。
不具合なのは以下の部分
#アメンバー申請へのリンクを探す #アメンバー申請へのリンクが見つかった場合には、ペタへのリンクとどちらが先か確認する if (amember_e_get = amember_entry.match(response)) and (entry_point >amember_e_get.begin(0)) amember_path = amember_e_get.to_s amember_path.sub!(/secret.ameba.jp/,'') http2 = Net::HTTP.new('secret.ameba.jp') http2.start amember_response = http2.get(amember_path, header) http2.finish if peta_entry.match(amember_response.body) peta_e_path = peta_blog_e_get.to_s posting_text = "from blog entry(amenber).." else peta_e_path = '/p/addPeta.do?targetAmebaId='+line+'&service=profile' posting_text = "from Profile(not amenber)..." end else peta_e_path = peta_blog_e_get.to_s posting_text = "from blog entry..." end
ペタへのリンクとアメンバー申請のリンクの前後関係を調べ、アメンバー申請のリンクが先の場合にはその記事をアメンバー限定記事の扱いにしたのだが、コレが不具合だった。
アメブロでは、画像付き記事とかの場合に記事の末尾ペタリンクの前に3件の『最近の画像付き記事』とかのリンク画像が付加されている。
その過去記事の中にアメンバー限定記事があった場合、上記スクリプトでは一般記事をアメンバー限定記事と誤判断してしまう。
横着なスクリプトではなかなか上手くいかないモノだ。