SHOWROOM - 自動星集め/種集め - 配信ルームリストの取得(ソース)
現在、SHOWROOMでの自動星集め/種集め、さらには自動星投げ/種投げツール(両方合わせれば自動三周ツール)の作成に必要な要素について記事を書いています。前記事 「SHOWROOM - 自動星集め/種集め - 配信ジャンルの取得(ソース)」 では公式、アマチュアそれぞれのジャンルの求め方について書いたので、今回はそれぞれのジャンルにある配信ルームのリストを作ることになります。
(次は「星集め関数」の予定です)
前回、今回の記事はブラウザを開きそこから必要なデータを取得する方法ですので、「SHOWROOM - イベントでの配信者の獲得ポイント数を取得する(改良版)」 や 「SHOWROOM - イベント貢献ランキング(貢献ポイント)を取得する関数(ソース)」 のようにブラウザを開かずJSONあるいはHTMLをスクレイピングする方法に比較すると若干パフォーマンス的に劣る方法になります。
じつはムム@SRさん( あるいは Showroom イベント ポイント遷移グラフ公開所)から
ONLIVEのリストを取得するだけであれば、SRのトップページが開かれた瞬間にhttps://t.co/vZMxQaHTou
— ムム@SR (@MmSwrm) August 7, 2019
から全ジャンルのONLIVEルームリスト(UPCOMINGリストは除く)を取得しているようですので、この返りのJSONをごにょごにょすればブラウザ要らず、かもです。
というご指摘をいただいています。要するにこの配信ルームのリストを作る機能もブラウザを開かずに(つまりgo/agoutiではなくJSONのパースだけで)作れるということです。そちらの方がパフォーマンス的に有利かと思いますが、すでにこの関数を作りかけていたのでひとまずこちらから公開することにします。JSON版もそのうち作って公開したいと思います。
プログラム自体それほど大きなものではありませんし、コメントも入れてあるので記事の最後にそのまま公開することにします。
main()(テストプログラム部)の実行にはGetCategoryList()が必要ですが、これはPackage ShowroomLibを作ってそれにおさめています(パッケージはビルドしたあとインストールが必要です。念のため)
もちろん前記事のソースからGetCategoryList()を持ってきてこのソースに追加してもかまいませんが、その場合は
IdxAmateur, IdxOfficial, status := ShowroomLib.GetCategoryList(...
のところはとうぜん
IdxAmateur, IdxOfficial, status := GetCategoryList(...
とします。
最近多少はGO言語やagoutiの使い方がわかってきたので、今までよりはだいぶマシなプログラムになっていると思います(あくまで"今までより"ですが)
セレクターはこれまでブラウザの開発ツールでCSSセレクターをコピーしてきてそれを使っていたのですが、かならずしも意図したものにならない場合があり、今回はhtmlの構造を考えながらセレクターを作っています。
また"li"のところのデータの取得ではMultiSelectionを使ってみました(セレクション取得のための All()、セレクション数を得る Count()、個別のセレクションを得る At() )
個別に取得するのとたいして違いはないのですが、今回は後ろからデータを取得しなければならないケースがあり最初に個数が必要なので。
※ 自動星集め・星投げについてはすでにソースを公開(「Showroom - 自動星集め・星投げ・カウントツール)」 )していますが、機能ごとにソースを分けてない上にふつうは必要にならないような機能を盛り込んだこともあってソースの可読性がよろしくないです。またハードコーティングされた部分もありますし、コメントの位置や量にムラがあります。そこでそのあたりを改善して自分の目的にあったプログラムを作っていただけるようにしようと、機能ごとに関数を分けて一つずつ記事にしている次第です。
もうひとつの 「Showroom - 自動三周ツール(もう一つの自動星集め・星投げ・カウントツール)」 の方もすでにあしかっぴ(@pf_ashika)さんから視聴ボーナス対応版のソースをいただいているので、公開予定ですが、私のソースをベースにされているため同じ課題が残っています。
package main
import (
"ShowroomLib"
"fmt"
"time"
"github.com/sclevine/agouti"
)
// 配信者ルームの情報
// "今後の展開"を考慮しstringの配列ではなく構造体としています。
type RoomInf struct {
URL string // 配信者ルームのURL
name string // 配信者ルームのタイトル
}
// 配信ルームのリストを作るときの順番
// InOrder 昇順
// 公式はアイドル、タレント・モデル、ミュージック、...と進み
// 毎日○○、ONLIVEの順でリストを作っていきます。
// アマチュアは初配信、ONLIVEの順でリストを作っていきます。
const InOrder = 1
// InReverseOreder 降順
// 公式はお笑い・トーク、声優・アニメ、ミュージック、...と進み
// ONLIVE、毎日○○の順でリストを作っていきます。
const InReversOrder = -1
/*
GetRoomList()
SHOWROOMの「オンライブ」画面から、指定されたカテゴリー位置のジャンルの現在配信中のルームのリストを取得します。
カテゴリー位置とはGetCategoryList()で取得した、公式/アマチュアの各ジャンルのオンライブ画面上の位置(順序)です。
取得したルームのリストはをスライスに格納して戻します。
GetCategoryList()については
「SHOWROOM - 自動星集め/種集め - 配信ジャンルの取得(ソース)」
http://seppina.cocolog-nifty.com/blog/2019/08/post-9b442d.html
引数
Direction int リストを作るときの順番(方向)
InOrder 昇順
InReverseOreder 降順
星集めを目的としたとき必要となる引数です。
なんらかの理由であまり時間をおかずにリストを作るとき、結果が似通ったものに
ならないように、つまりすでに星集めをしたところがリストに入らないようにするためです。
maxnoofroom int ルーム情報を取得するルームの数(上限)
これも星集めを目的としたときのためにあります。星集めは10ルーム分集めればいいので
配信ルームのリストは(データを収集した直後に配信をやめたルームがあるなど考えても)
20個もあれば十分ですから。
実際の取得数がここで指定したルーム数より少ないこともありえます。
page *agouti.Page ブラウザ画面のポインタ
nilであれば新たにブラウザを開きます。
ChromeTmpFolder string Chrome作業用フォルダ、事前にSHOWROOMを視聴できる環境を作っておきます。
CategoryList []int ルームリストを取得したいジャンルの位置リスト
通常GetCategoryList()で取得したIdxAmateur, IdxOfficialの
いずれかを渡します。
戻り値
RoomList []string 配信中ルームのURL(の最後の文字列)のリスト
statsu int 実行結果
0 正常終了(現状では必ず 0 を返します)
*/
func GetRoomList(Direction int, maxnoofroom int, page *agouti.Page, ChromeTmpFolder string, CategoryList []int) (
RoomList []RoomInf, status int) {
var roominf RoomInf
// ブラウザが開かれていない場合は、新たにブラウザを開きます。
// ここで開いたブラウザはこの関数が終了するときとじられます( ==> defer() )
if page == nil {
// Chromeを利用することを宣言
agoutiDriver := agouti.ChromeDriver()
agoutiDriver.Start()
defer agoutiDriver.Stop()
page, _ = agoutiDriver.NewPage(agouti.Desired(agouti.Capabilities{
"chromeOptions": map[string][]string{
"args": []string{
"user-data-dir=" + ChromeTmpFolder, // Hyperion
},
},
}),
)
}
// SHOWROOMオンライブ画面にいないときはオンライブ画面に移行
url, _ := page.URL()
if url != "https://www.showroom-live.com/onlive" {
page.Navigate("https://www.showroom-live.com/onlive")
time.Sleep(5 * time.Second)
}
// 指定されたジャンルそれぞれの配信中のルームをリストに追加していきます。
// 情報取得した配信ルームの数
n := 0
// 取得の順序(方向)に応じてジャンルの範囲を設定します。
var ib, ie, is int
if Direction == InOrder {
ib = 0
ie = len(CategoryList)
is = 1
} else {
ib = len(CategoryList) - 1
ie = -1
is = -1
}
// 三重ループを抜けるときのラベル
OuterLoop:
// すべてのジャンルについて繰り返します。
for i := ib; i != ie; i += is {
fmt.Println("category= ", CategoryList[i])
// 指定されたジャンルの画面に移行します。
FmtFrame := "#js-categorymenu-list > li:nth-child(%d)"
SelectorFrame := fmt.Sprintf(FmtFrame, CategoryList[i])
page.Find(SelectorFrame).Click()
time.Sleep(5 * time.Second)
// 取得の順序(方向)に応じて毎日○○、ONLIVE(初配信、ONLIVE)の取得順序を決めます。
var jb, je, js int
if Direction == InOrder {
jb = 1
je = 3
js = 1
} else {
jb = 2
je = 0
js = -1
}
// 毎日○○、ONLIVE(初配信、ONLIVE)について繰り返します。
for j := jb; j != je; j += js {
fmt.Println(" j= ", j)
// 配信ルームへのマルチセレクションとそのセレクション数を取得します。
Selector := fmt.Sprintf("#js-onlive-collection > div:nth-child(1) > section:nth-child(%d) > ul > li", j)
MSelectionToRoom := page.All(Selector)
NoOfRoom, _ := MSelectionToRoom.Count()
fmt.Println("No of Room = ", NoOfRoom)
// 取得の順序(方向)に応じて配信ルームの取得順序を決めます。
var kb, ke, ks int
if Direction == InOrder {
kb = 0
ke = NoOfRoom
ks = 1
} else {
kb = NoOfRoom - 1
ke = -1
ks = -1
}
// 配信ルームの分だけ繰り返します。
for k := kb; k != ke; k += ks {
// 配信ルームのURLを取得します。
roominf.URL, _ = MSelectionToRoom.At(k).Find(".listcard-join-btn").Attribute("href")
// 配信ルームのタイトルを取得します。
roominf.name, _ = MSelectionToRoom.At(k).Find(".listcard-name").Text()
fmt.Println(roominf.URL, roominf.name)
// 配信ルームの情報を取得できなかったとき。
// 現実にはこの条件を満たすことはないと思いますが....
if roominf.URL == "" {
continue
}
// 取得したデータを戻り値(用の変数)に格納します。
RoomList = append(RoomList, roominf)
// データ取得数が指定した数に達したら終了です。
n++
if n == maxnoofroom {
break OuterLoop
}
}
}
}
status = 0
return
}
/*
SHOWROOM関連関数のテスト用プログラム、対象は
GetCategoryList()
GetRoomList()
です。
実行には "CategoryName.txt" が必要です。
"CategoryName.txt" の内容はGetCategoryList()の説明にあります。
「SHOWROOM - 自動星集め/種集め - 配信ジャンルの取得(ソース)」
http://seppina.cocolog-nifty.com/blog/2019/08/post-9b442d.html
*/
func main() {
// Chromeを利用することを宣言
agoutiDriver := agouti.ChromeDriver()
agoutiDriver.Start()
defer agoutiDriver.Stop()
page, _ := agoutiDriver.NewPage(agouti.Desired(agouti.Capabilities{
"chromeOptions": map[string][]string{
"args": []string{
"user-data-dir=" + "E:\\Tmp\\Chrome11", // Hyperion
},
},
}),
)
IdxAmateur, IdxOfficial, status := ShowroomLib.GetCategoryList(
page, // *agouti.Page
"E:\\Tmp\\Chrome11", // Chrome作業用フォルダ、事前にSHOWROOMを視聴できる環境を作っておきます。
"CategoryName.txt", // ジャンルとそのタイプ(公式/アマチュア)のリストです。
)
fmt.Println(" status=", status)
fmt.Print(" IdxAmateur = ")
for i := 0; i < len(IdxAmateur); i++ {
fmt.Printf("%3d", IdxAmateur[i])
}
fmt.Println()
fmt.Print(" IdxOfficial = ")
for i := 0; i < len(IdxOfficial); i++ {
fmt.Printf("%3d", IdxOfficial[i])
}
fmt.Println()
RoomList, status := GetRoomList(
InOrder, // 昇順
20, // 情報を取得するルームの数の上限
page, // *agouti.Page
"E:\\Tmp\\Chrome11", // 環境設定済みのChrome作業フォルダ
IdxAmateur, // アマチュア枠リスト
)
fmt.Println(" status=", status)
fmt.Print(" Roomlist(アマチュア枠) = \n")
for i := 0; i < len(RoomList); i++ {
fmt.Printf("<%s>\n", RoomList[i].URL)
}
RoomList, status = GetRoomList(
InReversOrder, // 降順
100, // 情報を取得するルームの数の上限
page, // *agouti.Page
"E:\\Tmp\\Chrome11", // 環境設定済みのChrome作業フォルダ
IdxOfficial, // 公式枠リスト
)
fmt.Println(" status=", status)
fmt.Print(" Roomlist(公式枠) = \n")
for i := 0; i < len(RoomList); i++ {
fmt.Printf("<%s>\n", RoomList[i].URL)
}
}
« SHOWROOM - 自動星集め/種集め - 配信ジャンルの取得(ソース) | トップページ | SHOWROOM - 自動三周ツール(視聴ボーナス版)(もう一つの自動星集め・星投げ・カウントツール »
「パソコン・インターネット」カテゴリの記事
- さくらインターネットのレンタルサーバーでGOで書いたCGIを動かした(苦労)話(2021.04.19)
- SHOWROOMのAPI - 「ライブ情報」の取得(GO言語のソースつき)(2019.10.26)
- SHOWROOM 星集め・星投げツール スケジュールの詳細化 BreakDownSchedule() (三周のやり方を例に)(2019.09.25)
- SHOWROOM 新・自動三周ツール -- GO言語によるブラウザ制御 (1) main()(2019.09.17)
この記事へのコメントは終了しました。
コメント