« SHOWROOM - イベントでの配信者の獲得ポイント数を取得する(改良版) | トップページ | SHOWROOM - 自動星集め/種集め - 配信ジャンルの取得(ソース) »

2019年7月29日 (月)

SHOWROOM - イベント貢献ランキング(貢献ポイント)を取得する関数(ソース)

イベント貢献ランキングの取得については以前書いた

  Showroom - イベントの獲得ポイント数を取得して記録するツール

にもあったのですが、パフォーマンス(負荷)の問題があるので

  SHOWROOM - イベントでの配信者の獲得ポイント数を取得する(改良版)

と同じように書き直してみました。つまり go/agouti をやめて go/goquery を使っています。

また関数のインターフェースについては、最近のいくつかの記事と同様に

  1.  実行時のパラメータ(イベントIDや配信者ID)は引数として渡し
  2.  結果はすべて戻り値として受け取る
  3.  結果がリストの場合はSliceとして受け渡す

という方針にしました。ソースはそれほど長くないのでこの記事の最後にそのまま掲載します。

関数のインターフェースやサンプルプログラムの実行方法についてはコメントにあります。

ところで、貢献ポイントランキングを取得することに意味があるのか、というのがあるのですが、
まあぜったい必要になるというのは減算が発生したとき、原因アカウントを特定するときくらいでしょうか w
もっとも貢献ポイントランキングがあればかならず原因アカウントを特定できるわけでもありませんが。

配信者さんにとっては、○○くん、最近サボリ気味だから気合入れておこうかなあ、とか...

なお減算については

  「Showroom - 複数アカウント(複垢)問題の真実 - 実験計画
  「Showroomの重複アカウント(複垢)減算はこうして起きる


に書いたのですが、ムム@SRさん( あるいは Showroom イベント ポイント遷移グラフ公開所)によれば実際はもっと"複雑怪奇"なケースもあるようです。

サンプルプログラムの実行結果
Photo_20190729003701

じつはさらに(もうちょっとだけ)パフォーマンスがいい方法があるようです。公開に問題なさそうであれば、そのうち記事にします。

---------------------------------------------

/*
	SHOWROOMのイベント貢献ランキングを取得する関数とその使用例です。
 
	使い方
		イベントページのURLが
			https://www.showroom-live.com/event/event_id
		で、配信者さんのID(SHOWROOMへの登録順を示すと思われる6桁以下の数字)が
			ID_Account
		のとき
 
			% 実行モジュール名 event_id ID_Account
 
		と実行すると貢献ランキングの一覧が表示されます。
 
		例えば現時点(2019/07/28)でいちばん目立つところにあるイベントの一位さんの貢献ランキングを知りたいときは
 
			% 実行モジュール名 kc19aw_final 120380
 
		とします。
 
		Webページからのデータ取得の参考としては以下などがあります。
			「はじめてのGo言語:Golangでスクレイピングをしてみた」
			https://qiita.com/ryo_naka/items/a08d70f003fac7fb0808
			 ざくっとした内容ですがGO言語のインストールのところから書いてあります。
			 お時間のある方は系統的に書かれたものを探してじっくり勉強してください。
 
	GetPointsContA00.exe	2019/07/28 15:00
		新規作成
 
*/
package main
 
import (
	"fmt"
	"os"
	"strconv"
	"strings"
 
	"net/url"
 
	"github.com/PuerkitoBio/goquery"
)
 
/*
	GetPointsCont()
	イベントページのURLと配信者さんのIDから、イベント貢献ランキングのリストを取得します。
 
	引数
	EvnetName	string	イベント名、下記イベントページURLの"event_id"の部分
		https://www.showroom-live.com/event/event_id
	ID_Account	string	配信者さんのID
		SHOWROOMへの登録順を示すと思われる6桁(以下)の数字です。アカウントとは違います。
 
	戻り値
	NoListner	int			リスナーの数、現状最大100ですが、100を越えても問題ないです。
	RankingList	[]int		リスナーの順位
	PointList	[]int		リスナーの貢献ポイント
	ListnerList []string	リスナーの名前
 
	***
	リスナーさんの日々のあるいは配信ごとの貢献ポイントの推移がすぐにわかれば配信者さんもいろいろ手の打ちよう(?)が
	ありそうですが、「リスナーの名前」というのはリスナーさんが自由に設定・変更できるので貢献ポイントを追いかけて
	行くのはけっこうたいへんです。
	こまめに記録しておくと、減算ポイントが発生したときの原因アカウントの特定には使えないこともないです。
	(実際やってみるとわかるのですが、これはこれでなかなかたいへんです)
	なお、原因アカウントの特定、というのは犯人探しというような意味で言ってるわけじゃありませんので念のため。
 
*/
func GetPointsCont(EventName, ID_Account string) (NoListner int, RankingList, PointList []int, ListnerList []string) {
 
	//	貢献ランキングのページを開き、データ取得の準備をします。
	_url := "https://www.showroom-live.com/event/contribution/" + EventName + "?room_id=" + ID_Account
 
	doc, err := goquery.NewDocument(_url)
	if err != nil {
		panic(err)
	}
 
	u := url.URL{}
	u.Scheme = doc.Url.Scheme
	u.Host = doc.Url.Host
 
	//	各リスナーの情報を取得します。
	var selector_ranking, selector_listner, selector_point, ranking, listner, point string
	var iranking, ipoint int
 
	//	データを一つ取得するたびに(戻り値となる)リスナー数をカウントアップします。
	for NoListner = 0; NoListner < 100; NoListner++ {
 
		//	以下セレクターはブラウザの開発ツールを使って確認したものです。
 
		//	順位を取得し、文字列から数値に変換します。
		selector_ranking = fmt.Sprintf("table.table-type-01:nth-child(2) > tbody:nth-child(2) > tr:nth-child(%d) > td:nth-child(%d)", NoListner+2, 1)
		ranking = doc.Find(selector_ranking).Text()
 
		//	データがなくなったらbreakします。このときのNoListnerは通常100、場合によってはそれ以下です。
		if ranking == "" {
			break
		}
 
		iranking, _ = strconv.Atoi(ranking)
 
		//	リスナー名を取得します。
		selector_listner = fmt.Sprintf("table.table-type-01:nth-child(2) > tbody:nth-child(2) > tr:nth-child(%d) > td:nth-child(%d)", NoListner+2, 2)
		listner = doc.Find(selector_listner).Text()
 
		//	貢献ポイントを取得し、文字列から"pt"の部分を除いた上で数値に変換します。
		selector_point = fmt.Sprintf("table.table-type-01:nth-child(2) > tbody:nth-child(2) > tr:nth-child(%d) > td:nth-child(%d)", NoListner+2, 3)
		point = doc.Find(selector_point).Text()
		point = strings.Replace(point, "pt", "", -1)
		ipoint, _ = strconv.Atoi(point)
 
		//	戻り値となるスライスに取得したデータを追加します。
		RankingList = append(RankingList, iranking)
		PointList = append(PointList, ipoint)
		ListnerList = append(ListnerList, listner)
	}
 
	return
}
 
func main() {
 
	if len(os.Args) < 3 {
		fmt.Println("Usage: ", os.Args[0], " EventName ID_Account")
		return
	}
	EventName := os.Args[1]
	ID_Account := os.Args[2]
 
	NoListner, RankingList, PointList, ListnerList := GetPointsCont(EventName, ID_Account)
 
	for i := 0; i < NoListner; i++ {
		fmt.Printf("%d\t%d\t%s\r\n", RankingList[i], PointList[i], ListnerList[i])
	}
 
}
 

« SHOWROOM - イベントでの配信者の獲得ポイント数を取得する(改良版) | トップページ | SHOWROOM - 自動星集め/種集め - 配信ジャンルの取得(ソース) »

パソコン・インターネット」カテゴリの記事

コメント

 セッピーナ様、ご紹介下さいまして恐縮です。また、貴重なソースの公開、有難うございます。

 私の方でも実際に減算が起きたルームについて、貢献ランキングを手動保存しておいて比較してみたりしたのですが、貢献ランキング上は減算されたりランキングから消えたユーザは(私が確認したケースでは)無かったりします…。
 実際、そういったケースでは最終結果の貢献ランキングトップ100までのポイント合計だけで発表されたルームの最終獲得ポイントよりも大きな値になり、その値は減算を受けなかったと仮定した場合の値の方に近かったりします。

 皆様、考えることは同じで、減算されたルームの方々でこの貢献ランキングのポイント和を計算してみる方が多いようなので、実は私も単純に イベントとルームID(もしくはアカウントID)を入力したら、その時点の貢献ランキングの和が表示されるようなページが有っても良いかなぁ…と思っていた所でした(あくまでも思ってただけで実装するかどうか未定なのですが…需要が有りそうなら、という感じです)。

さっそくコメントいただきありがとうございます。恐縮です m(._.)m
私の経験した範囲内でも減算の発生が貢献ポイントランキングに影響を与えることはなかったです(=貢献ポイントが減算されることはなかった)

したがって
減算ポイント値 = 一昨日の貢献ポイント - 昨日の貢献ポイント
となるようなリスナーさんを探すことができれば、それが原因アカウントとなっていました。

ただ現実には複数のリスナーさんが原因アカウントになっていたり、減算ポイントがわかる正午近くや、一昨日・昨日の貢献ポイントが確定する時間帯に配信があったりでなかなか一筋縄ではいかないですね。

**追記**
最初に減算が発生したときは
  減算ポイント値 = 昨日までの貢献ポイント
ですね。

わわっ、貴重な情報、有難うございました。

何か、とても大きなヒント(というか答えそのもの?)を頂いた気が致します。イベントを通して繰り返し同一の、少数のユーザが減算されている場合は意外と特定できるケースも多いかもしれない…。
問題はいつ、どうやって&どういう形で実装するか…ですが…それもこちらのソースを使わせていただければ、随分と省力できると思いますので、ちょっと考えてみようかと思います。
重ねて有難うございました。

私も、もう一度減算の検証やってみようかなあ、とか思い始めました (^^)
二つのアカウントが複垢判定された場合どっちが減算されるかというところが完全に積めきれなかったもので...

この記事へのコメントは終了しました。

« SHOWROOM - イベントでの配信者の獲得ポイント数を取得する(改良版) | トップページ | SHOWROOM - 自動星集め/種集め - 配信ジャンルの取得(ソース) »

フォト

サイト内検索

  • 記事を探されるんでしたらこれがいちばん早くて確実です。私も使ってます (^^;; 検索窓が表示されるのにちょっと時間がかかるのはどうにかしてほしいです。

新着記事

リンク元別アクセス数

  • (アクセス元≒リンク元、原則PCのみ・ドメイン別、サイト内等除く)

人気記事ランキング

  • (原則PCのみ、直近2週間)
無料ブログはココログ