goquery как вывести текст с пагинацией?

Нужно чтобы при обнаружении текста в котором будут квадратные скобки [Rand]. Весь текст, что будет после них и до следующих кв.скобок заносился в массив. Фото для примера, взял отсюда https://genius.com/The-used-the-taste-of-ink-lyrics

Фото с примером

Уже есть почти готовый код, но никак не могу понять как его развить дальше

import (
    "fmt"
    "log"
    "net/http"
    "strings"

    "github.com/PuerkitoBio/goquery"
)

func FindTextSong(groupName, songName string) []string {
    songName = strings.ReplaceAll(songName, " ", "-")
    url := fmt.Sprintf("https://genius.com/%s-%s-lyrics", groupName, songName)

    res, err := http.Get(url)
    if err != nil {
        log.Fatal(err)
    }
    defer res.Body.Close()

    if res.StatusCode != 200 {
        log.Fatalf("Ошибка: состояние ответа %d", res.StatusCode)
    }

    doc, err := goquery.NewDocumentFromReader(res.Body)
    if err != nil {
        log.Fatal(err)
    }

    var date []string

    doc.Find("[class^='Lyrics__Container']").Each(func(i int, s *goquery.Selection) {
        text := s.Text()
        if strings.TrimSpace(text) != "" {
            date = append(date, text)
        }
    })
     return date
}

Ответы (1 шт):

Автор решения: Pak Uula

s.Text() удаляет все элементы и сливает строчки в одну.

Решение в лоб: итерировать s.Nodes и выбирать оттуда текст самостоятельно.

package main

import (
    "fmt"
    "log"
    "net/http"
    "strings"

    "github.com/PuerkitoBio/goquery"
    "golang.org/x/net/html"
)

func FindTextSong(groupName, songName string) (Song, error) {
    songName = strings.ReplaceAll(songName, " ", "-")
    url := fmt.Sprintf("https://genius.com/%s-%s-lyrics", groupName, songName)

    result := Song{}

    res, err := http.Get(url)
    if err != nil {
        return result, err
    }
    defer res.Body.Close()

    if res.StatusCode != 200 {
        return result, fmt.Errorf("Ошибка: состояние ответа %d", res.StatusCode)
    }

    doc, err := goquery.NewDocumentFromReader(res.Body)
    if err != nil {
        return result, err
    }

    currentVerse := Verse{
        Header: "",
        Lines:  []string{},
    }

    doc.Find("[class^='Lyrics__Container']").Each(func(i int, s *goquery.Selection) {

        sel := s.Contents()
        for _, n := range sel.Nodes {
            if n.Type == html.TextNode {
                text := strings.TrimSpace(n.Data)
                if text[0] == '[' {
                    if currentVerse.Header != "" {
                        result = append(result, currentVerse)
                        currentVerse = Verse{}
                    }
                    currentVerse.Header = text
                } else {
                    currentVerse.Lines = append(currentVerse.Lines, text)
                }
            }
        }
        if currentVerse.Header != "" {
            result = append(result, currentVerse)
        }
    })
    return result, nil
}

func main() {
    song, err := FindTextSong("The-used", "the-taste-of-ink")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(song)
}


type Verse struct {
    Header string
    Lines  []string
}

func (l Verse) String() string {
    return l.Header + "\n" + strings.Join(l.Lines, "\n")
}

type Song []Verse

func (s Song) String() string {
    builder := &strings.Builder{}
    for _, v := range s {
        builder.WriteString(v.String())
        builder.WriteRune('\n')
    }
    return builder.String()
}

В своём ответе я добавил типы Song и Verse для представления песни и отдельных куплетов/припевов

Этот пример работает для genius.com, так как там строки целиком и без элементов форматирования, но в общем случае надо анализировать тип узла и заканчивать строку только для узлов <br>, <p>, <div> и прочих с display=block, и игнорировать / заменять на пробелы остальные узлы-элементы.

→ Ссылка