Go 爬虫 解析 xml

Go 爬虫抓取解析 xml

导入爬虫用到的库

Python
import ( "encoding/xml" // xml 标准库 "fmt" // 打印" "io/ioutil" // ioutil 包实现了一些 I/O 实用函数。 "net/http" // http 请求库 )
1
2
3
4
5
6
7
8
9
10
11
import (
    "encoding/xml"
    // xml 标准库
    "fmt"
    // 打印"
    "io/ioutil"
    // ioutil 包实现了一些 I/O 实用函数。
    "net/http"
    // http 请求库
)
 

定义抓取函数

Python
// 抓取 url xml 返回 []byte func getXML(url string) ([]byte, error) { resp, err := http.Get(url) // 请求 url if err != nil { return []byte{}, fmt.Errorf("GET error: %v", err) } defer resp.Body.Close() // 清理内存 if resp.StatusCode != http.StatusOK { return []byte{}, fmt.Errorf("Status error: %v", resp.StatusCode) } // 根据状态码 判断是否正常 data, err := ioutil.ReadAll(resp.Body) if err != nil { return []byte{}, fmt.Errorf("Read body: %v", err) } return data, nil }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 抓取 url xml 返回 []byte
func getXML(url string) ([]byte, error) {
    resp, err := http.Get(url)
    // 请求 url
    if err != nil {
        return []byte{}, fmt.Errorf("GET error: %v", err)
    }
    defer resp.Body.Close()
    // 清理内存
 
    if resp.StatusCode != http.StatusOK {
        return []byte{}, fmt.Errorf("Status error: %v", resp.StatusCode)
    }
    // 根据状态码 判断是否正常
 
    data, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return []byte{}, fmt.Errorf("Read body: %v", err)
    }
 
    return data, nil
}
 

xml 格式

Go 爬虫 解析 xml

定义xml 的 struct

Python
type rss struct { XMLName xml.Name `xml:"rss"` Items []itemD `xml:"channel>item"` } type itemD struct { Title string `xml:"title"` PubDate string `xml:"pubDate"` Link string `xml:"link"` }
1
2
3
4
5
6
7
8
9
10
11
type rss struct {
    XMLName xml.Name `xml:"rss"`
    Items []itemD `xml:"channel>item"`
}
 
type itemD struct {
    Title string `xml:"title"`
    PubDate string `xml:"pubDate"`
    Link string `xml:"link"`
}
 

struct 和 xml 格式对应

rss struct 对应 xml
Go 爬虫 解析 xml

itemD struct 对应 xml
Go 爬虫 解析 xml

主函数

Python
func main() { url :="https://rsshub.app/fx678/kx" bytes,_:= getXML(url) var ss rss xml.Unmarshal(bytes,&ss) // 解包 for index, value := range ss.Items{ fmt.Println(index,value.Link, value.PubDate, value.Title) } // 由于 ss.Items 是个数组,所以采用 for 循环遍历 }
1
2
3
4
5
6
7
8
9
10
11
12
13
func main() {
    url :="https://rsshub.app/fx678/kx"
    bytes,_:= getXML(url)
    var ss rss
    xml.Unmarshal(bytes,&ss)
    // 解包
    for index, value := range ss.Items{
        fmt.Println(index,value.Link, value.PubDate, value.Title)
    }
//  由于 ss.Items 是个数组,所以采用 for 循环遍历
 
}
 

输出如下:

Go 爬虫 解析 xml

全部代码如下:

Python
package main import ( "encoding/xml" "fmt" "io/ioutil" "net/http" ) // 抓取 url xml 返回 []byte func getXML(url string) ([]byte, error) { resp, err := http.Get(url) // 请求 url if err != nil { return []byte{}, fmt.Errorf("GET error: %v", err) } defer resp.Body.Close() // 清理内存 if resp.StatusCode != http.StatusOK { return []byte{}, fmt.Errorf("Status error: %v", resp.StatusCode) } // 根据状态码 判断是否正常 data, err := ioutil.ReadAll(resp.Body) if err != nil { return []byte{}, fmt.Errorf("Read body: %v", err) } return data, nil } type rss struct { XMLName xml.Name `xml:"rss"` Items []itemD `xml:"channel>item"` } type itemD struct { Title string `xml:"title"` PubDate string `xml:"pubDate"` Link string `xml:"link"` } // 变量一定要大写 // 定义结构体 func main() { url :="https://rsshub.app/fx678/kx" bytes,_:= getXML(url) var ss rss xml.Unmarshal(bytes,&ss) for index, value := range ss.Items{ fmt.Println(index,value.Link, value.PubDate, value.Title) } // 由于 ss.Items 是个数组,所以采用 for 循环遍历 }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package main
 
import (
    "encoding/xml"
    "fmt"
    "io/ioutil"
    "net/http"
)
 
// 抓取 url xml 返回 []byte
func getXML(url string) ([]byte, error) {
    resp, err := http.Get(url)
    // 请求 url
    if err != nil {
        return []byte{}, fmt.Errorf("GET error: %v", err)
    }
    defer resp.Body.Close()
    // 清理内存
 
    if resp.StatusCode != http.StatusOK {
        return []byte{}, fmt.Errorf("Status error: %v", resp.StatusCode)
    }
    // 根据状态码 判断是否正常
 
    data, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return []byte{}, fmt.Errorf("Read body: %v", err)
    }
 
    return data, nil
}
 
 
type rss struct {
    XMLName xml.Name `xml:"rss"`
    Items []itemD `xml:"channel>item"`
}
 
type itemD struct {
    Title string `xml:"title"`
    PubDate string `xml:"pubDate"`
    Link string `xml:"link"`
}
// 变量一定要大写
// 定义结构体
 
func main() {
    url :="https://rsshub.app/fx678/kx"
    bytes,_:= getXML(url)
    var ss rss
    xml.Unmarshal(bytes,&ss)
 
    for index, value := range ss.Items{
        fmt.Println(index,value.Link, value.PubDate, value.Title)
    }
//  由于 ss.Items 是个数组,所以采用 for 循环遍历
 
}
 
 

另外一个库 更方便 etree

Python
package main import ( "fmt" "github.com/levigross/grequests" ) import "github.com/beevik/etree" func main() { url := "https://rsshub.app/fx678/kx" xml_source, _ := grequests.Get(url, nil) doc := etree.NewDocument() if err := doc.ReadFromString(xml_source.String()); err != nil { panic(err) } root := doc.SelectElement("rss") root = root.SelectElement("channel") for _, item := range root.SelectElements("item") { title := item.SelectElement("title").Text() url := item.SelectElement("link").Text() fmt.Println(title, url) } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main
 
import (
    "fmt"
    "github.com/levigross/grequests"
)
import "github.com/beevik/etree"
 
func main() {
    url := "https://rsshub.app/fx678/kx"
    xml_source, _ := grequests.Get(url, nil)
    doc := etree.NewDocument()
    if err := doc.ReadFromString(xml_source.String()); err != nil {
        panic(err)
    }
    root := doc.SelectElement("rss")
    root = root.SelectElement("channel")
    for _, item := range root.SelectElements("item") {
        title := item.SelectElement("title").Text()
        url := item.SelectElement("link").Text()
        fmt.Println(title, url)
    }
 
}
 
 
Go 爬虫 解析 xml

Go 爬虫 解析 xml