Goquery загружает пустой документ из явно не пустого ответа - PullRequest
0 голосов
/ 25 октября 2019

Я пытался загрузить ответ в документ goquery, но, похоже, он не работает (хотя он не выдает ошибок).

Ответ, который я пытаюсь загрузить, получен:

https://www.bbcgoodfood.com/search_api_ajax/search/recipes?sort=created&order=desc&page=4

и хотя он не выдает никаких ошибок, когда я звоню fmt.Println(goquery.OuterHtml(doc.Contents())), я получаю вывод:

<html><head></head><body></body></html>

Тем временем, если я не пытаюсь загрузить его вgoquery document и вместо этого звоните

s, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(s))

Я получаю:

<!doctype html>
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8 no-touch" lang="en"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9 no-touch" lang="en"> <![endif]-->
<!--[if gt IE 8]> <html class="no-js gt-ie-8 no-touch" lang="en"> <![endif]-->
<!--[if !IE]><!-->
<html class="no-js no-touch" lang="en">
<!--<![endif]-->

<head>
    <meta charset="utf-8">
    <title>Search | BBC Good Food</title>
    <!--[if IE]><![endif]-->
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <link rel="prev" href="https://www.bbcgoodfood.com/search/recipes?page=3&amp;sort=created&amp;order=desc" />
    <link rel="next" href="https://www.bbcgoodfood.com/search/recipes?page=5&amp;sort=created&amp;order=desc" />
    <meta name="robots" content="noindex" />
    <style>
        .async-hide {
            opacity: 0 !important
        }
    ... etc

Основная логика того, что я делаю, такова:

package main

import (
    "fmt"
    "net/http"
    "github.com/PuerkitoBio/goquery"
    "io/ioutil"
)

func main() {
    baseUrl := "https://www.bbcgoodfood.com/search_api_ajax/search/recipes?sort=created&order=desc&page="
    i := 4

    // Make a request
    req, _ := http.NewRequest(http.MethodGet, fmt.Sprintf("%s%d", baseUrl, i), nil)

    // Create a new HTTP client and execute the request
    client := &http.Client{}
    resp, _ := client.Do(req)

    // Print out response
    s, _ := ioutil.ReadAll(resp.Body)
    fmt.Println(string(s))

    // Load into goquery doc
    doc, _ := goquery.NewDocumentFromReader(resp.Body)
    fmt.Println(goquery.OuterHtml(doc.Contents()))
}

полный ответ можно найти здесь . Есть ли какая-то конкретная причина, по которой это не загружается?

1 Ответ

1 голос
/ 25 октября 2019

html-парсер Go, похоже, не похож на html, который вы получаете - теги <html> все находятся в комментариях, поэтому я думаю, что он просто никогда не приступит к анализу.

Если вы добавитедокумент с <html> оттуда все отлично работает. Один из способов сделать это - использовать обёртку для чтения, что-то вроде следующего, который записывает html-тег при первом вызове Read и делегирует resp.Body при последующих вызовах.

import "io"

var htmlTag string = "<html>\n"

type htmlAddingReader struct {
    sentHtml bool
    source io.Reader
}

func (r *htmlAddingReader) Read(b []byte) (n int, err error) {
    if !r.sentHtml {
        copy(b, htmlTag)
        r.sentHtml = true
        return len(htmlTag), nil
    } else {
        return r.source.Read(b)
    }
}

Чтобы использовать это в своем примере кода, измените последний раздел следующим образом:

    // Load into goquery doc
    wrapped := &htmlAddingReader{}
    wrapped.source = resp.Body
    doc, _ := goquery.NewDocumentFromReader(wrapped)
    fmt.Println(goquery.OuterHtml(doc.Contents()))
...