课程任务需要,用GO爬取网页上的问句数据。先上代码:
func GetData(arr *[]string) {
baseUrl := "https://www.ecook.cn/wenda/?page="
for page := 1; page <= 100; page++ {
fmt.Printf("第一个网页:开始爬取第%d页\n", page)
arrPage := []string{}
url := baseUrl + strconv.Itoa(page)
p, err := goquery.ParseUrl(url)
if err != nil {
panic(err)
}
t := p.Find(".content-cell-title")
for i := 0; i < t.Length(); i++ {
d := t.Eq(i).Text()
arrPage = append(arrPage, d)
}
*arr = append(*arr, arrPage...)
}
}
先进入网页查看总共有多少页,然后遍历每页。首先解析url
拿到节点对象,然后通过Find
函数查找制定类名的节点,接着遍历节点数组,拿到每个节点的文本。
func GetData2(arr *[]string) {
baseUrl := "https://www.xinshipu.com/question?page="
for page := 1; page <= 900; page++ {
fmt.Printf("第二个网页:开始爬取第%d页\n", page)
arrPage := []string{}
url := baseUrl + strconv.Itoa(page)
p, err := goquery.ParseUrl(url)
if err != nil {
panic(err)
}
p.Find("a[rel=questionClk]").Each(func(i int, node *goquery.Node) {
d := node.Child[0].Data
arrPage = append(arrPage, d)
})
*arr = append(*arr, arrPage...)
}
}
第二个网页的代码类似,但在操作过程中发现需求节点的类名带有空格,从而无法识别。左查右试一直没搞好,索性转化思路,先拿到其父节点,然后再取子节点的第一个,最后顺利拿到数据。
两个函数都是传入的数组指针,获取的数据直接添加到主函数的数组上,非常方便。
拿到数据之后需要将数据写入到csv文件,基本都是固定的写法:
func WriteData(data []string) {
wData := make([][]string, 50000)
// 按列写入数据
for i := 0; i < len(data); i++ {
wData[i] = make([]string, 1)
wData[i][0] = data[i]
}
f, err := os.Create("qes.csv") //创建文件
if err != nil {
panic(err)
}
defer f.Close()
f.WriteString("\xEF\xBB\xBF") // 写入UTF-8 BOM
w := csv.NewWriter(f) //创建一个新的写入文件流
w.WriteAll(wData) //写入数据
w.Flush()
}
需要注意的是,每一个小单元的数据添加进总数据的时候要按列添加,否则最后的文件就是一整行,不利于处理。
最后上主函数:
func main() {
data := []string{}
GetData(&data)
GetData2(&data)
WriteData(data)
fmt.Printf("爬取完成,共计%d条记录", len(data))
}