質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

Q&A

解決済

1回答

523閲覧

package htmlのNode structの使い方

Palo_Punte

総合スコア21

Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

0グッド

0クリップ

投稿2020/06/23 11:33

<div> <dl> <dt> <ul> <li>男</li> </ul> </dt> <dd>太郎</dd> <dt> <ul> <li>男</li> <li>man</li> </ul> </dt> <dd>次郎</dd> <dt> <ul> <li>女</li> </ul> </dt> <dd>花子</dd> </dl> </div>
all_human := [][]string{} doc.Find("div > dl").Each(func(index int, selection *goquery.Selection) { gender := selection.Find("dt > ul").Nodes name := selection.Find("dd").Nodes for i := 0; i < len(name); i++ { if gender[i].FirstChild.NextSibling.NextSibling.FirstChild.Data != "" { all_human = append(all_human, []string{gender[i].FirstChild.NextSibling.FirstChild.Data + gender[i].FirstChild.NextSibling.NextSibling.FirstChild.Data, name[i].FirstChild.Data}) }else{ all_human = append(all_human, []string{gender[i].FirstChild.NextSibling.FirstChild.Data, name[i].FirstChild.Data}) } } }) fmt.Println(all_human)

[["男","太郎"],["男man","次郎"],["女","花子"]]のようにしたいのですがどのようにすれば良いのでしょうか?
上記のようなif文ですとinvalid memory address or nil pointer dereferenceとなってしまいうまくできません。

また、https://godoc.org/github.com/grengojbo/goquery/exp/html#Node
を見てもフィールドや関数の種類がないのでできないのかもしれないのですが<ul>タグ以下の文字をまとめて取得のようにする簡単な方法はあるのでしょうか?
FirstChild.NextSibling.NextSibling.FirstChild.Dataのように長くなってしまう事を可能であれば避けたいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nobonobo

2020/06/24 02:45

github.com/grengojbo/goquery latest release v0.3.2 にはexp/htmlパッケージがありません。 再現しにくくて回答が難しいです。 experimentalなフィーチャーに関して回答が欲しい場合は experimentalなパッケージインストールにつかった手順、Goのバージョンなども示してください。
Palo_Punte

2020/06/24 06:41

情報不足で大変申し訳ございませんでした。goは1.13.8になります go get github.com/PuerkitoBio/goquery でgoqueryをインストールしselection *goquery.SelectionにNodesを使ってみると普通に使えたため、標準で使える仕様になっているのかなと思っていました 自分の実験のファイル でimportをしているものは "fmt" "github.com/PuerkitoBio/goquery" "math/rand" "net/http" "net/url" "strings" "time" "unicode" になります
guest

回答1

0

ベストアンサー

ドキュメントのリンク「https://godoc.org/github.com/grengojbo/goquery」は
github.com/PuerkitoBio/goquery とは全く関係ないドキュメントですのでご注意ください。

特に標準以外のパッケージを利用している場合、
import文はかなり重要な情報なので質問される際は省略しないほうがよろしいかと思います。

僕なりの回答は以下になります。
基本ドキュメントをパースした時に存在しないノードはnilになっているので
それを確認するようにしてください。(空文字のDataをもつノードをわざわざ用意をしてくれることはないようです)

github.com/PuerkitoBio/goqueryの狙いみたいなものはわからないので
なぜこうする必要があるのかについては回答できないです。

https://play.golang.org/p/dMzn_9QqIj8

go

1package main 2 3import ( 4 "bytes" 5 "fmt" 6 "log" 7 8 "github.com/PuerkitoBio/goquery" 9) 10 11const src = ` 12<div> 13 <dl> 14 <dt> 15 <ul> 16 <li>男</li> 17 </ul> 18 </dt> 19 <dd>太郎</dd> 20 <dt> 21 <ul> 22 <li>男</li> 23 <li>man</li> 24 </ul> 25 </dt> 26 <dd>次郎</dd> 27 <dt> 28 <ul> 29 <li>女</li> 30 </ul> 31 </dt> 32 <dd>花子</dd> 33 </dl> 34</div> 35` 36 37func main() { 38 doc, err := goquery.NewDocumentFromReader(bytes.NewBuffer([]byte(src))) 39 if err != nil { 40 log.Fatal(err) 41 } 42 all_human := [][]string{} 43 doc.Find("div > dl").Each(func(index int, selection *goquery.Selection) { 44 gender := selection.Find("dt > ul").Nodes 45 name := selection.Find("dd").Nodes 46 for i := 0; i < len(name); i++ { 47 if gender[i].FirstChild.NextSibling.NextSibling.NextSibling != nil { 48 all_human = append(all_human, []string{gender[i].FirstChild.NextSibling.FirstChild.Data + 49 gender[i].FirstChild.NextSibling.NextSibling.NextSibling.FirstChild.Data, 50 name[i].FirstChild.Data}) 51 } else { 52 all_human = append(all_human, []string{gender[i].FirstChild.NextSibling.FirstChild.Data, 53 name[i].FirstChild.Data}) 54 } 55 } 56 }) 57 fmt.Println(all_human) 58}

ツリーを参照するコードが長くなる件はFindをもっと活用すれば良いように思いました。

投稿2020/06/24 12:14

編集2020/06/24 12:19
nobonobo

総合スコア3367

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Palo_Punte

2020/06/24 14:45

>github.com/PuerkitoBio/goquery とは全く関係ないドキュメントですのでご注意ください。 すいません。goqueryだけを見て同じものだと思い込んでしまいました。 >import文はかなり重要な情報なので質問される際は省略しないほうがよろしいかと思います。 divタグとかもconst srcで入れれる事を教えて頂けたので次からはすぐに実行ができる状態で投稿をさせて頂こうと思います お手間を取らせてしまい申し訳ございませんでした 問題は、Dataとnilの比較だったのが原因だったのですね!気がつきませんでした FirstChildとNextSiblingも改行も一つと数える?ようなので理解に手間取ってしまったのですがなんとか取得をする事が無事にできました お手間をかけさせてしまい大変申し訳御座いませんでした。ご回答ありがとう御座いました
nobonobo

2020/06/24 22:52

NextSiblingが余計に必要な理由はよくよく考えると、 `<div>text1<span>text2</span>text3</div>` こういう場合に 以下のようなツリーになっているということみたいです。 DIV  TEXT(text1)  SPAN   TEXT(text2)  TEXT(text3)
Palo_Punte

2020/06/25 08:02

ありがとうございます 私の方でも色々タグの位置を変えて調べて見ておりました <ul> <li>男</li> </ul> と <ul><li>男</li></ul> も違うみたいなのですね 感覚的に少しわかってきました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問