一開始要先說爬蟲是什麼呢?
跟據維基的定義其中一段:
網路爬蟲可以將自己所存取的頁面儲存下來,以便搜尋引擎事後生成索引供用戶搜尋。
可以理解成有個機器人,自動的幫你查看網頁,並且處理好資料
這些資料還會自己去更新
在後續有需要用到相關資料時,就不用自己再去查詢跟整理了
目前搜尋引擎也都是靠自動網路爬蟲去尋找關鍵字結果
很多人爬蟲都會想到用python
但其實Golang本身對於網路的支持性本來就高
所以也是可以試試用Golang喔
以下是以原生的庫達到爬股票代碼的範例
將本國上市證券國際證券辨識號碼一覽表的網頁
自動處理成csv檔案以供之後作使用:
package mainimport ( "log" "strings" "bytes" "encoding/csv" "io/ioutil" "net/http" "os" "golang.org/x/text/transform" "github.com/PuerkitoBio/goquery" "golang.org/x/text/encoding/traditionalchinese")func init() { log.SetFlags(log.Ldate | log.Lshortfile)}func main() { // FindStockNumber() FindStockNumberBySTDLib()}// 'dtype', '國際證券辨識號碼', '上市日', '市場別', '產業別', 'CFI', '備註'type Stock struct { Dtype string IdetifyNumber string Date string MarketCategory string IndustryCategory string CFI string Note string}func FindStockNumberBySTDLib() { log.Print("Visiting http://isin.twse.com.tw/isin/C_public.jsp?strMode=2") resp, err := http.Get("http://isin.twse.com.tw/isin/C_public.jsp?strMode=2") if err != nil { log.Println("Get url error.") return } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { log.Printf("get content failed status code is %d. \n", resp.StatusCode) return } BodyBytes, err := ioutil.ReadAll(resp.Body) if err != nil { log.Println("HTML body read error.") return } log.Println("Get HTML.") // 將抓到的html網頁資訊交給goquery解析 htmlDoc, err := goquery.NewDocumentFromReader(bytes.NewReader([]byte(BodyBytes))) if err != nil { log.Println("Goquery parse fail.") return } var StockList []Stock htmlDoc.Find(".h4").Each(func(j int, contentSelection *goquery.Selection) { var stock Stock contentSelection.Find("tr[align!='center']").Each(func(_ int, tr *goquery.Selection) { tr.Find("td[colspan!='7']").Each(func(i int, s *goquery.Selection) { // 轉換編碼 decodeStr, _ := DecodeBig5([]byte(s.Text())) data := string(decodeStr) number := i % 8 switch number { case 0: stock.Dtype = data case 1: stock.IdetifyNumber = data case 2: stock.Date = data case 3: stock.MarketCategory = data case 4: stock.IndustryCategory = data case 5: stock.CFI = data case 6: stock.Note = data } }) StockList = append(StockList, stock) }) }) f, err := os.Create("./StockList.csv") if err != nil { return } f.WriteString("\xEF\xBB\xBF") defer f.Close() fw := csv.NewWriter(f) // 'dtype', '國際證券辨識號碼', '上市日', '市場別', '產業別', 'CFI' fw.Write([]string{"有價證券代號", "名稱", "國際證券辨識號碼(ISIN Code)", "上市日", "市場別", "產業別", "CFI", "備註"}) sep := string([]byte{227, 128, 128}) for _, i := range StockList { SplitStr := strings.Split(i.Dtype, sep) if len(SplitStr) > 1 { fw.Write([]string{ SplitStr[0], SplitStr[1], i.IdetifyNumber, i.Date, i.MarketCategory, i.IndustryCategory, i.CFI, i.Note, }) } else { fw.Write([]string{ i.Dtype, " ", i.IdetifyNumber, i.Date, i.MarketCategory, i.IndustryCategory, i.CFI, i.Note, }) } } fw.Flush() log.Println("Write to .csv success.")}//convert BIG5 to UTF-8func DecodeBig5(s []byte) ([]byte, error) { I := bytes.NewReader(s) O := transform.NewReader(I, traditionalchinese.Big5.NewDecoder()) d, e := ioutil.ReadAll(O) if e != nil { return nil, e } return d, nil}//convert UTF-8 to BIG5func EncodeBig5(s []byte) ([]byte, error) { I := bytes.NewReader(s) O := transform.NewReader(I, traditionalchinese.Big5.NewEncoder()) d, e := ioutil.ReadAll(O) if e != nil { return nil, e } return d, nil}
處理過程中
要記得編碼的部分
不然後面整理成CSV的時候
會變成亂碼
在我的github上也可以找到這個範例喔
佶曰:網路爬蟲比蝸牛爬得快
沒有留言:
張貼留言