Разделить элемент на разрыв строки с помощью GoQuery - PullRequest
0 голосов
/ 08 мая 2018

Я пытаюсь получить контент со страницы с помощью GoQuery, но по некоторым причинам я не могу сделать разбиение на разрыв строки (br).

HTML-код выглядит следующим образом:

<ul>
    <li>I'm skipped</li>

    <li> 
        Text Into  - <p>Whatever</p>
        <p>
            Line 1<br />
            Line 2<br />
            Line 3<br />
            Line 4<br />
            Line N
        </p>
    </li> 
</ul>

Go код:

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

doc.Find("ul").Each(func(i int, s *goquery.Selection) {

    str := s.Find("li p").Next().Text()

    fmt.Println(str, "--")

})

По какой-то причине я не могу получить каждую строку, разделённую пробелом в теге p, как отдельный элемент. Выход кода выше:

Line1Line2Line3Line4LineN--

Но вывод, который я пытаюсь достичь, должен выглядеть следующим образом:

Line1--
Line2--
Line3--
Line4--
LineN--

Поскольку я новичок в Go, пожалуйста, дайте мне знать в комментариях. Если что-то не понятно, я постараюсь объяснить это настолько, насколько я знаю.

Спасибо.

Ответы [ 4 ]

0 голосов
/ 04 июня 2019

Думаю, будет лучше, если вы просто замените <br/> на '\ n' или '-' перед вызовом .Text() метода.

    // html is the result of `.Html()` method
    str := strings.Replace(html, "<br/>", "\\n", -1)
    doc, err := goquery.NewDocumentFromReader(strings.NewReader(str))
    if err != nil {
        return ""
    }
    return doc.Text()
0 голосов
/ 08 мая 2018

Я запустил код, который вы показали, и получаю переводы строки. Предполагая, что вы используете последнюю версию goquery, вы тоже должны быть, , если ваш html не

<p>
    Line 1<br />
    Line 2<br />
    Line 3<br />
    Line 4<br />
    Line N
</p>

но на самом деле это что-то вроде:

<p>
    Line 1<br />Line 2<br />Line 3<br />Line 4<br />Line N
</p>

(имея в виду, что, например, когда вы открываете инструменты разработчика Chrome, вероятно, отображает его как первое, даже если фактический источник является последним)

В этом случае ожидается ожидаемое поведение:

let html_1 = $(`<p>
        Line 1<br />
        Line 2<br />
        Line 3<br />
        Line 4<br />
        Line N
    </p>`);

let html_2 = $(`<p>
        Line 1<br />Line 2<br />Line 3<br />Line 4<br />Line N
    </p>`);
    
console.log({html1: html_1.text(), html2: html_2.text()});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Чтобы решить, вы, вероятно, могли бы просто сделать:

p := s.Find("li p").Next()
p.SetHtml(strings.Replace(p.Html(), "<br />", "<br />\n", -1)).Text()

хотя, возможно, вам придется поиграть с тем, использовать ли <br/> или <br /> или <br>, так как я не уверен, как он это отрендерит.

0 голосов
/ 08 мая 2018

.Text() будет:

Текст получает объединенное текстовое содержимое каждого элемента в наборе совпадающие элементы, включая их потомков.

Так что вы действительно хотите получить содержимое и отфильтровать все теги br. Как гласит ответ Дэйва, там есть новые символы строки, поэтому я также обрезал их:

package main

import (
    "fmt"
    "github.com/PuerkitoBio/goquery"
    "strings"
)

var input string = `
<ul>
    <li>I'm skipped</li>

    <li> 
        Text Into  - <p>Whatever</p>
        <p>
            Line 1<br />
            Line 2<br />
            Line 3<br />
            Line 4<br />
            Line N
        </p>
    </li> 
</ul>
`

func main() {
    doc, err := goquery.NewDocumentFromReader(strings.NewReader(input))
    if err != nil {
        panic(err)
    }

    doc.Find("ul").Each(func(i int, s *goquery.Selection) {

        p := s.Find("li p").Next()
        p.Contents().Each(func(i int, s *goquery.Selection) {
            if !s.Is("br") {
                fmt.Println(strings.TrimSpace(s.Text()), "--")
            }

        })

    })
}

Производит:

Line 1 --
Line 2 --
Line 3 --
Line 4 --
Line N --
0 голосов
/ 08 мая 2018

Хорошо, мне удалось найти одно решение. Не уверен, что это правильный путь, поэтому, если у кого-то есть что-то лучше - поделитесь им.

Таким образом, я в основном сохраняю значение li p как HTML, а затем использую strings.Split для разбиения каждого тега br, а поскольку strings.Split возвращает фрагмент строки, я просто зацикливаюсь на нем.

title, err := s.Find("li p").Next().Html()
if err != nil {
    panic(err)
}

splittedTitles := strings.Split(title, "<br/>")

for _, str := range splittedTitles {
    fmt.Println(str, "--")
}
...