golang 爬蟲簡單實戰
第一步先安裝 elasticsearch,因爲爬蟲數據量特別大,如果靠着我們手動刷新進入文件無疑非常耗費時間,所以數據用來存儲在 elasticsearch 上面,有這麼幾點好處
-
天然支持分佈式高併發,隨時分佈式 p2p 擴容
-
全文索引查詢毫秒級別
-
在線統計分析引擎可以動態在線處理數據
這裏我就用 docker 來進行安裝 elasticsearch 了
# 最好加上版本號 不然可能會報錯
docker run -d -p 9200:9200 elasticsearch:5.6.9
# 然後查看啓動狀態
docker ps
看到容器啓動成功後就可以通過 localhost:9200 訪問了~
對於爬蟲呢 ,其實沒那麼高大尚 ,我們在瀏覽器輸入一個 url,然後就進入我們想要的頁面,從 http 層面來看,我們發起一個 request 請求後,會有一個 response 響應,而我們需要的信息都在 response body 裏面,爬蟲就是把 response body 的數據經過正則的篩選然後拿到而已。
先看看一個入門的案例~
func zhai() {
resp, err := http.Get("https://www.zhenai.com/n/message?from=myzhenai")
if err != nil {
panic(err)
}
defer resp.Body.Close()
//utf8Reader := transform.NewReader(resp.Body, simplifiedchinese.GBK.NewDecoder())
if resp.StatusCode == http.StatusOK {
all, err := ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
}
bytes := printWomen(all)
for _, m := range bytes {
for _, subMatch := range m {
fmt.Printf("%s ", string(subMatch))
}
fmt.Println()
}
fmt.Println("找到 :", len(bytes))
}
}
// 正則解析器
func printWomen(contents []byte) [][][]byte {
re := regexp.MustCompile(`<a target="_blank" href="//(www.zhenai.com/zhenghun/[0-9a-zA-Z]+)".[^>]*>([^<]+)</a> `)
matches := re.FindAllSubmatch(contents, -1)
return matches
}
func main() {
zhai()
}
這就是我們所爬取的信息~ 當然這是通過正則來達到的效果,正則表達式可以自己簡單瞭解下,很簡單的~
網站一般都會有反爬機制,像上面這個網站沒有,但如果把網址換成豆瓣,大家就可以看到返回的狀態嗎是 418 了(俗稱茶壺狀態碼~),不過這種反爬只是通過 UA(User-Agent)來驗證是否是瀏覽器訪問還是代碼訪問而已,咱們弄個簡單的 UA 僞裝就行。
看上圖控制檯,那就是 UA 身份了,瀏覽器 f12 打開控制檯找到 Network 的 Request Headers 就可以看到我們自己的 UA 了,然後寫進代碼就行了
這兒就是設置了 UA 僞裝,這個時候就可以正常爬豆瓣了!
單機版爬蟲流程圖
下面上代碼
// 啓動函數 main方法
func main() {
engine.Run(engine.Request{
Url: "https://book.douban.com/",
ParseFunc: parse.ParseContent,
})
}
// engine包的type類
type Request struct {
Url string
ParseFunc func([]byte) ParseResult //該函數用於參數解析 正則
}
type ParseResult struct {
Requests []Request
Items []interface{}
}
func NilParse([]byte) ParseResult {
return ParseResult{}
}
// engine包的engine類
func Run(seeds ...Request) {
var requests []Request
for _, e := range seeds {
requests = append(requests, e)
}
for len(requests) > 0 {
r := requests[0]
requests = requests[1:]
log.Printf("fetching url: %s", r.Url)
body, err := fetcher.Fetch(r.Url)
if err != nil {
log.Printf("Fetch Error: %s", r.Url)
continue
}
parseResult := r.ParseFunc(body)
requests = append(requests, parseResult.Requests...)
for _, item := range parseResult.Items {
fmt.Printf("got item: %s\n", item)
}
}
}
// fetcher包的fetch類
func Fetch(url string) ([]byte, error) {
client := &http.Client{}
req, err := http.NewRequest("GET", url, nil)
req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36")
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
fmt.Printf("Error status code :%d", resp.StatusCode)
}
result, err := ioutil.ReadAll(resp.Body)
return result, err
}
// 正則解析標籤 parse包下的parseTag類
const regexpStr = `<a href="([^"]+)">([^"]+)</a>`
func ParseContent(content []byte) engine.ParseResult{
res := regexp.MustCompile(regexpStr)
matches := res.FindAllSubmatch(content, -1)
result := engine.ParseResult{}
for _, m := range matches {
result.Items = append(result.Items, m[2])
result.Requests = append(result.Requests, engine.Request{
Url: "https://book.douban.com/" + string(m[1]),
ParseFunc: engine.NilParse,
})
}
return result
}
這就是一個簡單的爬蟲了,幾乎可以訪問目前所有的網站了
類似淘寶這種大型網站其反爬機制肯定很難,但只要可以訪問,就一定可以爬,做好 UA 僞裝、cookie 認證、代理 ip、token 認證等一堆機制,也不是爬不了,當然爬到的內容都是咱們可以看到的,比如密碼這種東西,就不是爬蟲可以爬到的了,所以爬蟲也不是萬能的~
這是爬淘寶頁面的數據,並不是程序錯誤,只是每個人的 token 都不一樣,所以有些需要登陸才能訪問的頁面就會報錯 404,帶上自己的 token 就好了~
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/kU4gpf2AGQRcezy8s8T0nQ