19日に更新してた

アフィリエイトはないよ

chromedp で AttributeValue とか Text とか

chromedp をつかってAttributeValue を取ってみました。
radiko のトップページのヘッダー部分の放送局のリストから data-id とテキストを抜き出してみようかとやってみました。

radiko.jp

package main

import (
	"context"
	"fmt"
	"strings"

	"github.com/chromedp/cdproto/cdp"
	"github.com/chromedp/chromedp"
)

func main() {
	allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), []chromedp.ExecAllocatorOption{
		chromedp.NoFirstRun,
		chromedp.NoDefaultBrowserCheck,

		chromedp.Headless,

		chromedp.Flag("disable-extensions", false),
		chromedp.Flag("enable-automation", false),
		chromedp.Flag("restore-on-startup", false),

		chromedp.UserDataDir("D:\\chromeuserprofile"),
	}...)
	defer cancel()

	ctx, cancel := chromedp.NewContext(allocCtx, chromedp.WithErrorf(log.Printf))
	defer cancel()

	var rows []*cdp.Node
	var res string
	var rowlist []string

	err := chromedp.Run(ctx,
		chromedp.Navigate(`https://radiko.jp/`),
		chromedp.Nodes(
			// /html/body/div[1]/div[1]/header/div[2]/div/div[2]/div/ul/li[1]/a TBS これはコメントを外しても通りません。
			// `html body div div header div div div div ul li a`,
			`ul li a`,
			// `.header__station-list ul li a`,
			&rows,
			chromedp.ByQueryAll,
		),
		chromedp.Text(`//*[@id="station-list"]`, &res, chromedp.NodeVisible),
		// chromedp.Text(`.header__station-list ul`, &res, chromedp.NodeVisible),

	)
	if err != nil {
		log.Println(err)
	}
	for _, c := range rows {
		cu := c.AttributeValue("data-id")
		if len(cu) != 0 {
			rowlist = append(rowlist, cu)
		}
	}
	res0 := strings.Fields(res)
	fmt.Println(rowlist, res0)
}

>>[TBS QRR LFR RN1 RN2 INT FMT FMJ JORF BAYFM78 NACK5 YFM IBS HOUSOU-DAIGAKU JOAK JOAK-FM] [TBSラジオ 文化放送 ニッポン放送 ラジオNIKKEI第1 ラジオNIKKEI第2 interfm TOKYO FM J-WAVE ラジオ日本 bayfm78 NACK5 FMヨコハマ LuckyFM 茨城放送 放送大学 NHKラジオ第1(東京) NHK-FM(東京)]

東京だと radiko の放送局の最初が TBS ラジオで path*1 は /html/body/div[1]/div[1]/header/div[2]/div/div[2]/div/ul/li[1]/a となっていますが、`html body div div header div div div div ul li a`, でも `ul li a`, でもどちらでも通りますので、loop 回して AttributeValue で採取できます。ベタにやる際には div[1] とかあるのは無視して、当てはまるものは全部取って来て後で考えるか、クラス表記を併用したほうが良いようです。*2

少し変えて c.AttributeValue("href" ) にするとリンクが取得できますが、`ul li a`, だとページ中のほぼ全部になってしまいます。で、 `html body div div header div div div div ul li a`, でリンクを取得しても、

/#!/top
/#!/timeshift
/#!/areafree
/#!/recommend
/#!/popular
/#!/history
http://faq.radiko.jp/
/#!/live/TBS
/#!/live/QRR
/#!/live/LFR
/#!/live/RN1
/#!/live/RN2
/#!/live/INT
/#!/live/FMT
/#!/live/FMJ
/#!/live/JORF
/#!/live/BAYFM78
/#!/live/NACK5
/#!/live/YFM
/#!/live/IBS
/#!/live/HOUSOU-DAIGAKU
/#!/live/JOAK
/#!/live/JOAK-FM

欲しい部分は "/#!/live/TBS" 以降なのですが、前段の部分も出て来ます。

で ".header__station-list ul li a" とクラス表記をドットを付けて書いた上でタグを記載するとうまく取得できました。

Text は `station-id` と書くと同じレベルの "番組表" まで入ってきましたので xpath を使いましたが、".header__station-list ul" でもOK。*3

*1:っていうのだろうか?

*2:AttributeValue だと同じタグ中に attribute が複数あっても特定のものが取り出せますので便利です。r5,9,25追記

*3:適当に作ったテスト用をそのまま記載したから変数名が rows とか cu とか、本当に変数名つけるの下手だな、と反省。