Showroomでの自動星集めの試み (3) ガチイベ、最後の5分間
後から考えるとこの記事ではこうやっておけばよかったというようなところがたくさんあります。方法を多少は改善した記事が
「Showroom - イベントの獲得ポイント数を取得して記録するツール」
にあります。
-------------------------
タイトルには“ガチイベ”と書いたのですが、正確にはガチイベの予選の話です。とは言えガチイベらしさは出てると思います。
Go/agouti による自動星集めを検討しているわけですが、プログラミングにも少しは慣れてきたのでガチイベの最後の4時間、獲得ポイント数上位の方たちの獲得ポイントの推移を調べてみました。
対象としたイベントは
「TP公式番組アシスタントMCの奪取イベント!(東京エリア B予選)」
です。どういうイベントなのかは上のリンクの中にあります。イベント特典(つまりこのイベントの価値)も書いてありますが、今回は予選ですので特典は“上位5名が決勝に出られる”ことになります。つまり1位でも5位でもいいけれど5位と6位は天と地ほど違うということです。
このイベントを選んだ理由は、私が応援している配信者さんが参加していたから、という単純な理由です。
イベント最終日の14時の時点での獲得ポイント数上位8名の方の獲得ポイントの推移を17時からイベントが終了する21時直前まで取得してグラフにしました。
イベント終了時の獲得ポイントはどうやって調べるのかわからなかったので貢献ポイント上位100名の貢献ポイントの合計に貢献ポイント100位の方のポイントの50倍をプラスするとして求めています。特に根拠のある方法でなく、ここは今後検討してみたいと思います。
ポイントとはなんぞや、みたいな話は省略します。この記事に興味を持たれる方には不要な話だと思いますので...
(データは数分おきに取得しているため重複があります。最後の1時間についてはグラフを見やすくするため重複データを間引きしてあります。データは8位の方の分までとったのですが、7位と8位の方は110万pt以下だったのでこのグラフには表示されません)
途中ちょっとした動きはありますが、イベント終了30分前くらいまでは配信者さんそれぞれについて(配信していないと思われる時間帯は除き)一定の傾きで上昇しています。
リスナーさんが星・種を投げたりカウントしてたりしているのに相当すると思われます。星・種やカウントの数は1時間あたり500個あるいは一配信あたり50カウントと上限が決まっていますので、こうなるのは当然でしょう。
配信終了の30分くらい前からじょじょに傾きが大きくなってきます。有料のギフトを投げはじめているものと思われます。そして最後の5分間のあいだに一挙にポイントが上昇します。
14時の時点で4位だった配信者・Dさん(紫)は、終了5分前でもまだ4位のままだったのですが、5分の間にポイントを30万ポイント程度増やし堂々の一位になります。6位だった配信者・Fさん(橙)も15万ポイントを増やし4位に4位に滑り込み決勝進出の権利を獲得しています。
1位、2位だった配信者さんは30分くらい前から有料ギフトを断続的に投げていますが、最後の5分間で集中的に投げるというのはあんまりやられていないようです。結果として1位だったAさん(青)は3位、2位だったBさん(赤)は5位に落ちてしまっています。とくにBさんはあやうく決勝進出の権利を逃すところでした。
これを見てどう感じるかは人それぞれと思いますが、Showroomのイベント、特にガチイベと言われるイベントの怖さを感じます。
-------------------------
参考
「Showroom - 自動星集め・星投げ・カウントツール)」 (使用法とソースつき)
「Showroom - 自動三周ツール(もう一つの自動星集め・星投げ・カウントツール)」
「Showroom - イベントの獲得ポイント数を取得して記録するツール」
「Showroom - 福引するプログラムとその結果 (1)」
「Showroom - イベント結果データ」
「Showroomの複数アカウント(複アカ、複垢)について考えてみた(1)」
「Showroom - 複数アカウント(複垢)問題の真実 - 実験計画」
「Showroomの重複アカウント(複垢)減算はこうして起きる」
「Showroomでの自動星集めの試み (3) ガチイベ、最後の5分間
「Showroom ラスカルイベの最後の5分間」
「Showroomでの自動星集めの試み (1)」
「Showroomでの自動星集めの試み (2) 配信ルームの一覧を作る」
「Showroomでの自動星集めの試み (4) 星集めツール」
「Showroomでひたすらリスナーレベルを上げるための星集めツール(Go/Agouti)」
「超初心者のGo言語/agouti - ブラウザ操作の基本の基本」
「超初心者のGo言語 - 複数の戻り値をもつ関数」
「超初心者のGo言語 - もっとも簡単なGoroutine(並列処理)」
---------------------
「GoDoc - package agouti」
「Qiita @0829 - Goではじめてみたブラウザの自動操作」
「Qiita @tenten0213 - agoutiというWebDriverクライアントを使って面倒な作業を自動化する」
「Qiita @masaru_b_cl - Windows上でGo言語初心者向け学習環境を作る」
「はじめてのGo言語」
「天才まくまくノート - まくまく Hugo/Go ノート - 関数を定義する (func)」
「Qiita @TakaakiFuruse - Golang Goの並列処理を学ぶ(goroutine, channel)」
「Qiita @To_BB - Rubyエンジニアがゴルーチン(Go言語)を学んでみた【初心者向け】」
「Qiita @fukumone - goroutine 使い方まとめ」
=======
今回はGo/agoutiによるプログラムとバッチファイルを使ってデータを取得しています。
バッチ処理がGoの処理を1分間ごとに呼び出しています。ファイルへの書き込みは追記で行いますの実行を途中で打ち切ったり再開しても問題ありません。
なおGoの処理の中で2箇所ウェイトが入っています。二番目のウェイトは必須です。これがないとデータを取得できませんでした。最初のウェイトはループ一回目のデータが欠落することがあるため入れてみたのですが効果があったのかなかったのかよくわかりません。
なお注意していただきたいのはどんなイベントでもこの方法で獲得ポイントのデータを取得できるわけではないということです。イベントごとに画面の構成は違います。
package main
import "github.com/sclevine/agouti"
import "fmt"
import "os"
import "time"
import "strings"
func main() {
// 14時の時点での1位から8位の方のルームのURLをリストにしてあります。
SiteName := [...]string{
"https://www.showroom-live.com/tps_1107",
"https://www.showroom-live.com/shun_tps",
"https://www.showroom-live.com/tps_0612",
"https://www.showroom-live.com/supica_tps2",
"https://www.showroom-live.com/217_tps",
"https://www.showroom-live.com/tps_0819",
"https://www.showroom-live.com/u3d6f9g4",
"https://www.showroom-live.com/529midori_tps2"}
// Chromeを利用することを宣言
agoutiDriver := agouti.ChromeDriver()
agoutiDriver.Start()
defer agoutiDriver.Stop()
page, _ := agoutiDriver.NewPage()
// このウェイトはループの最初の処理でデータを取得できないことがあったため入れました。
// 意味なかったのかも....
time.Sleep(10000 * time.Millisecond)
fmt.Println(time.Now())
// ファイルは追記でオープンします。なければ新たに作られます。
f, _ := os.OpenFile("TPS.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
// データをとりはじめた時刻をファイルに書き出します。
t := time.Now()
hh, mm, ss := t.Clock()
LogTime := fmt.Sprintf("%02d:%02d:%02d", hh, mm, ss)
f.WriteString(LogTime)
// リストにあるURLの分繰り返します。
for _, Name := range SiteName {
f.WriteString(",")
// 配信者のルームを開きます。
page.Navigate(Name)
// このイベントはイベントページに獲得ポイントが表示されています。
page.FindByClass("event-body").Click()
// このウェイトがないとデータを取得することができませんでした。
time.Sleep(2000 * time.Millisecond)
// 現在の合計ポイントの項目を取得します。
Point, _ := page.Find("#js-genre-section-1 > div > ul > li").Text()
// ポイントの両側にある不要な文字列を削除します。
f.WriteString(strings.TrimSuffix(strings.TrimPrefix(Point, "現在の合計ポイント:"), "pt"))
// この処理はイベントページのクローズのつもりです。
// この操作でイベントページがクローズするか確認していません。
// おそらくこの処理がなくても全体的な動作には問題ないような。
page.Find("#event-detail-dialog > a").Click()
}
// すべての配信者さんを巡回したら処理を終わりファイルはクローズします。
f.WriteString("\r\n")
f.Close()
}
バッチ処理timeout実行中はctrl-Cで実行を打ち切ることができます。上記のプログラムをコンパイルし tps.exe を作ってあります。
:loop
tps
type tps.log
timeout 60
goto loop
« Showroomでの自動星集めの試み (2) 配信ルームの一覧を作る | トップページ | Showroomでの自動星集めの試み (4) 星集めツール »
「パソコン・インターネット」カテゴリの記事
- さくらインターネットのレンタルサーバーでGOで書いたCGIを動かした(苦労)話(2021.04.19)
- SHOWROOMのAPI - 「ライブ情報」の取得(GO言語のソースつき)(2019.10.26)
- SHOWROOM 星集め・星投げツール スケジュールの詳細化 BreakDownSchedule() (三周のやり方を例に)(2019.09.25)
- SHOWROOM 新・自動三周ツール -- GO言語によるブラウザ制御 (1) main()(2019.09.17)
コメント
この記事へのコメントは終了しました。
« Showroomでの自動星集めの試み (2) 配信ルームの一覧を作る | トップページ | Showroomでの自動星集めの試み (4) 星集めツール »
セッピーナさんこんばんわ(*´ω`*)
いろんな統計取ってるんですね!
自分も最近統計取り始めたので勉強になります。
イベ終了後の実際のポイントが分からないのが不便ですよね。
自分の方法も確実性はないのですが下記のように計算しています。
下記のデータはイベ終了前で実際に採取できるデータから計算しています。
0:00をイベ終了直前のポイント
0:05をイベ終了後のポイント
と仮定して計算しています。
----------
【データ】
Time 0:00
2721193 (実際のポイント)
2423624 (100位までの合計)
297569 (上記2つの差)
151700 (100位を50倍)
Time 0:05
2723053 (実際のポイント)
2425348 (100位までの合計)
297705 (上記2つの差)
151700 (100位を50倍)
【計算】
0:00の『上記2つの差』と0:05の『100位までの合計』から0:05の実際のポイントを算出
2425348(0:05の100位までの合計) + 297569(0:00の上記2つの差)
= 2722917(予測ポイント)
2723053(0:05の実際のポイント) - 2722917(予測ポイント)
= 136
誤差136ptは運が良かったのですが、ある程度誤差がない範囲で予測できそうです。
参考になれば幸いです(*´ω`*)
こういう話ができる方が周りに少ないので、話してもらえると嬉しいです!
投稿: のりたか | 2018年1月 3日 (水) 23時58分
のりたかさん、コメントありがとうございます。
今のところデータの量が少なすぎてどういう推測をしても正しいか正しくないかわからないというのが現状です。
そういう意味で貴重なコメントありがとうございます m(._.)m
今日最終日の、3週間で1位が1200万ポイントというイベント(ラスカルイベント)を目撃(?)できました。特殊なケースになるのかもしれませんが、こういうのも参考にできるだけ正確な推算方法を作っていきたいと思っています。
投稿: セッピーナ | 2018年1月 4日 (木) 01時45分
更新タイミングもルームによって違うので正確な計算って難しいですよねぇ
また情報楽しみにしてます!
投稿: のりたか | 2018年1月 4日 (木) 01時56分
5分に一回表示が更新されるという話を聞いていたので2分おきにデータをとると言う方法を使っています。処理の途中で更新されることがあるのですが、一更新中に2~3回データが得られるので前後を見ればどういう動きをしているかわかると思われます。
せっかくGo言語を使っているのでこの部分は並行処理にすればほぼ同一タイミングでデータを取得できるのではないかと考えています。さらに更新の時刻を特定した上で時計を見ながら処理ししていけば完璧なはずなんですが、いつまでかかることやら (^^;;
投稿: セッピーナ | 2018年1月 4日 (木) 15時02分
自分の場合は、1回目は5秒毎にデータの更新を感知させて情報更新、waitを270秒挟んで10秒間隔に更新確認→データの更新を感知したらまたwaitのような形でなるべくサーバーに負担かけずに同期取れないものか模索中ですw
あとそれぞれのルームで更新タイミングが違うのに、得られるデータ(ポイント差)などは早い方も遅い方も同じなんですよね。
早いルームは更新直前のポイントも反映されてるかもしれないんですが、遅いルームは30秒以上前の古いデータかもしれません。
星、ギフト、カウントのデータ引っ張ってきてリアルタイムのポイント変動がある程度分かるんですが、その更新タイミングの差の影響でどうしても誤差が出てしまいます(泣)
GO言語の並列処理良いですね(*´ω`*)
使ったことなかったので調べてみます!
投稿: のりたか | 2018年1月 5日 (金) 11時25分
なるほどデータ更新のタイミングと表示のタイミングと別にあるわけですね。
で、少なくとも表示のタイミングはバラバラなわけですか。
有用な情報ありがとうございます m(._.)m
投稿: セッピーナ | 2018年1月 5日 (金) 12時15分
表示ポイントの情報更新のタイミングがわかりました!
ただルームごとに違うので、実際はいつのポイントでどれぐらい時間差があるかは分かりません。
でも色々使いようがある内容なので書いておきますね。
1515142800 ←1月5日18時0分0秒の時間です
1515142821 ←1月5日18時0分21秒の時間です。配信開始時間です。
下記が更新タイミングです
【2018-01-05 18:02:20 +0900】
【2018-01-05 18:07:21 +0900】
【2018-01-05 18:12:20 +0900】
【2018-01-05 18:17:21 +0900】
【2018-01-05 18:22:20 +0900】
【2018-01-05 18:27:19 +0900】
【2018-01-05 18:32:20 +0900】
【2018-01-05 18:37:20 +0900】
【2018-01-05 18:42:20 +0900】
【2018-01-05 18:47:20 +0900】
【2018-01-05 18:52:21 +0900】
1515150016 (配信開始時刻 20時00分16秒)
下記が更新タイミングです
【2018-01-05 20:02:15 +0900】
【2018-01-05 20:07:15 +0900】
【2018-01-05 20:12:15 +0900】
【2018-01-05 20:17:15 +0900】
【2018-01-05 20:22:15 +0900】
【2018-01-05 20:27:16 +0900】
【2018-01-05 20:32:16 +0900】
【2018-01-05 20:37:15 +0900】
1秒ほどの誤差はありますが、基本的に配信を始めて2分後から5分間隔みたいです。
時間差はどれぐらいあるのか知りたいですねぇ
投稿: のりたか | 2018年1月 6日 (土) 00時09分
なるほど、配信開始時刻で更新時刻が決まるわけですか。
となると配信開始時刻は取得できるので、それから更新のタイミングを知ることができますね。
詳しいデータありがとうございました m(._.)m
投稿: セッピーナ | 2018年1月 6日 (土) 12時00分