This commit is contained in:
chai2010
2016-01-18 11:14:19 +08:00
parent a91355f5f1
commit 884ada9cd0
20 changed files with 116 additions and 92 deletions

View File

@@ -11,25 +11,25 @@ golang.org/x/net/html
package html
type Node struct {
Type NodeType
Data string
Attr []Attribute
FirstChild, NextSibling *Node
Type NodeType
Data string
Attr []Attribute
FirstChild, NextSibling *Node
}
type NodeType int32
const (
ErrorNode NodeType = iota
TextNode
DocumentNode
ElementNode
CommentNode
DoctypeNode
ErrorNode NodeType = iota
TextNode
DocumentNode
ElementNode
CommentNode
DoctypeNode
)
type Attribute struct {
Key, Val string
Key, Val string
}
func Parse(r io.Reader) (*Node, error)
@@ -43,21 +43,21 @@ gopl.io/ch5/findlinks1
package main
import (
"fmt"
"os"
"fmt"
"os"
"golang.org/x/net/html"
"golang.org/x/net/html"
)
func main() {
doc, err := html.Parse(os.Stdin)
if err != nil {
fmt.Fprintf(os.Stderr, "findlinks1: %v\n", err)
os.Exit(1)
}
for _, link := range visit(nil, doc) {
fmt.Println(link)
}
doc, err := html.Parse(os.Stdin)
if err != nil {
fmt.Fprintf(os.Stderr, "findlinks1: %v\n", err)
os.Exit(1)
}
for _, link := range visit(nil, doc) {
fmt.Println(link)
}
}
```
@@ -66,17 +66,17 @@ visit函數遍歷HTML的節點樹從每一個anchor元素的href屬性獲得l
```Go
// visit appends to links each link found in n and returns the result.
func visit(links []string, n *html.Node) []string {
if n.Type == html.ElementNode && n.Data == "a" {
for _, a := range n.Attr {
if a.Key == "href" {
links = append(links, a.Val)
}
}
}
for c := n.FirstChild; c != nil; c = c.NextSibling {
links = visit(links, c)
}
return links
if n.Type == html.ElementNode && n.Data == "a" {
for _, a := range n.Attr {
if a.Key == "href" {
links = append(links, a.Val)
}
}
}
for c := n.FirstChild; c != nil; c = c.NextSibling {
links = visit(links, c)
}
return links
}
```
@@ -109,21 +109,21 @@ http://www.google.com/intl/en/policies/privacy/
```Go
gopl.io/ch5/outline
func main() {
doc, err := html.Parse(os.Stdin)
if err != nil {
fmt.Fprintf(os.Stderr, "outline: %v\n", err)
os.Exit(1)
}
outline(nil, doc)
doc, err := html.Parse(os.Stdin)
if err != nil {
fmt.Fprintf(os.Stderr, "outline: %v\n", err)
os.Exit(1)
}
outline(nil, doc)
}
func outline(stack []string, n *html.Node) {
if n.Type == html.ElementNode {
stack = append(stack, n.Data) // push tag
fmt.Println(stack)
}
for c := n.FirstChild; c != nil; c = c.NextSibling {
outline(stack, c)
}
if n.Type == html.ElementNode {
stack = append(stack, n.Data) // push tag
fmt.Println(stack)
}
for c := n.FirstChild; c != nil; c = c.NextSibling {
outline(stack, c)
}
}
```
@@ -153,10 +153,10 @@ $ ./fetch https://golang.org | ./outline
大部分編程語言使用固定大小的函數調用棧常見的大小從64KB到2MB不等。固定大小棧會限製遞歸的深度當你用遞歸處理大量數據時需要避免棧溢出除此之外還會導致安全性問題。與相反,Go語言使用可變棧棧的大小按需增加(初始時很小)。這使得我們使用遞歸時不必考慮溢出和安全問題。
練習**5.1** :脩改findlinks代碼中遍歷n.FirstChild鏈表的部分將循環調用visit改成遞歸調用。
**練習 5.1** 脩改findlinks代碼中遍歷n.FirstChild鏈表的部分將循環調用visit改成遞歸調用。
練習**5.2** : 編寫函數記録在HTML樹中出現的同名元素的次數。
**練習 5.2** 編寫函數記録在HTML樹中出現的同名元素的次數。
練習**5.3** : 編寫函數輸出所有text結點的內容。註意不要訪問`<script>``<style>`元素,因爲這些元素對瀏覽者是不可見的。
**練習 5.3** 編寫函數輸出所有text結點的內容。註意不要訪問`<script>``<style>`元素,因爲這些元素對瀏覽者是不可見的。
練習**5.4** : 擴展vist函數使其能夠處理其他類型的結點如images、scripts和style sheets。
**練習 5.4** 擴展vist函數使其能夠處理其他類型的結點如images、scripts和style sheets。