以前一直都是再用Python写爬虫,最近想体验下Golang写爬虫的感受,因此就有了这个系列。我想要抓取的页面是豆瓣Top250页面,选择它的理由有3个:html
咱们先看初版的代码。git
按逻辑我把抓取代码分红2个部分:github
咱们先看HTTP请求,Golang语言的HTTP请求库不须要使用第三方的库,标准库就内置了足够好的支持:golang
import (
"fmt"
"net/http"
"io/ioutil"
)
func fetch (url string) string {
fmt.Println("Fetch Url", url)
client := &http.Client{}
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("User-Agent", "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)")
resp, err := client.Do(req)
if err != nil {
fmt.Println("Http get err:", err)
return ""
}
if resp.StatusCode != 200 {
fmt.Println("Http status code:", resp.StatusCode)
return ""
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("Read error", err)
return ""
}
return string(body)
}
复制代码
我把URL请求的逻辑都放在了fetch函数中,里面作了一些异常处理。值得说的有2点:web
接着就是解析页面的部分:正则表达式
import (
"regexp"
"strings"
)
func parseUrls(url string) {
body := fetch(url)
body = strings.Replace(body, "\n", "", -1)
rp := regexp.MustCompile(`<div class="hd">(.*?)</div>`)
titleRe := regexp.MustCompile(`<span class="title">(.*?)</span>`)
idRe := regexp.MustCompile(`<a href="https://movie.douban.com/subject/(\d+)/"`)
items := rp.FindAllStringSubmatch(body, -1)
for _, item := range items {
fmt.Println(idRe.FindStringSubmatch(item[1])[1],
titleRe.FindStringSubmatch(item[1])[1])
}
}
复制代码
这篇文章咱们主要体验用标准库完成页面的解析,也就是用正则表达式包regexp来完成。不过要注意须要用strings.Replace(body, "\n", "", -1)
这步把body内容中的回车符去掉,要否则下面的正则表达式.*
就不符合了。FindAllStringSubmatch
方法会把符合正则表达式的结果都解析出来(一个列表),而FindStringSubmatch
是找第一个符合的结果。bash
Top250页面是要翻页的,最后在main函数里面实现抓取所有Top250页面。另外为了和以后的改进作对比,咱们加上代码运行耗时的逻辑:函数
import (
"time"
"strconv"
)
func main() {
start := time.Now()
for i := 0; i < 10; i++ {
parseUrls("https://movie.douban.com/top250?start=" + strconv.Itoa(25 * i))
}
elapsed := time.Since(start)
fmt.Printf("Took %s", elapsed)
}
复制代码
在Golang中把数字转成字符串须要使用strconv.Itoa
(嘿嘿,本博客域名就是这个模块),这样就能够根据start的参数的不通拼出正确的页面路径。用一个for循环完成翻页。post
运行起来很是快:fetch
❯ go run crawler/doubanCrawler1.go
... # 省略输出
Took 1.454627547s
复制代码
经过终端输出能够看到咱们拿到了对应电影条目的ID和电影标题!
完整代码能够在这个地址找到。