大家好,我是谢伟,一名程序员。之前接触的语言是Python, 编程领域学会的第一个技能是『爬虫』,凭借着爬虫技术先后在两个创业公司从事的是『网络爬虫』这份活。
研究生毕业后,基于各方面的考虑,选择的是现在的这份工作。主要的是从事『云计算』方面的工作,再细化点,主要从事云计算中的 PaaS 部署相关的工作。
目前正在着手的任务是开发一款命令行工具。支持 PaaS 部署相关的各种命令,且开发语言是 go。
我熟悉的是 Python ,借着之前的编程基础,顺利的转到了 go 语言。很自觉的会比较两款语言的相似和不同之处。同时我越来越理解到:『编程语言只是工具』这句话的含义。
言归正传:下面使用 go 语言实现一个简单的爬虫。已经有了 python 爬虫技能,为什么需要进行 go 爬虫的实现版?为了更加的熟悉 go 的语言特性。
我们已经知道:一个简易的标准爬虫的步骤是
获取网页内容:
使用 HTTP 不同动作获取网页内容
网页内容解析:
正则表达式或者各种解析工具
解析的内容的处理:
文件处理、数据库处理等
最近数字货币很火,当然风险也很大,这里我们不谈数字货币。我们的目标是爬虫市值前100 的数字货币的相关信息。
抓取网站:https://www.feixiaohao.com/
抓取内容:0、排名 1、名称 2、流通市值 3、价格 4、流通数量 5、成交额 6、涨幅
效果:输出市值前 100 的数字货币的上述7个字段的信息
表示某个数字货币的信息。
type CoinInfo struct {
Rank string `json:"rank"`
Name string `json:"name"`
CurrentCount string `json:"current_count"`
CurrentPrice string `json:"current_price"`
CurrentMark string `json:"current_mark"`
Count string `json:"count"`
Change string `json:"change"`
}
func (h *HttpClientImpl) Get(url string) ([]byte, error) {
client := &http.Client{}
req, err := httpclient.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
respBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
err = errors.New("GET: http client.Do[" + url + "] response error, status code: " +
string(resp.StatusCode) + ", response body: " + string(respBody))
//log.Error("infra", err)
return respBody, err
}
return respBody, nil
}
第三方库,需要自己安装
doc, err := goquery.NewDocument("https://www.feixiaohao.com/")
以网页源代码中的一个数字货币为例:
<tr id="bitcoin">
<td>1</td>
<td>
<a href="/currencies/bitcoin/" target="_blank">
<img src="//static.feixiaohao.com/coin/7033f2f2c2a16094bbb3bafc47205ba8_small.png" alt="BTC-比特币">BTC-比特币
</a>
</td>
<td class="market-cap" data-usd="134254523787" data-cny="844272998288" data-btc="16887331">¥8,443亿 </td>
<td><a href="/currencies/bitcoin/#markets" target="_blank" class="price" data-usd="7964" data-cny="50081" data-btc="1">¥50,081</a></td>
<td>1,686万</td>
<td><a href="/currencies/bitcoin/#markets" target="_blank" class="volume" data-usd="7039549769.62554" data-cny="44268915134.0379" data-btc="888529.229834415">¥4,426,892万</a></td>
<td class="change">
<span class="text-red">-9.65%</span>
</td>
<td class="char">
<span class="line2" data-peity='{"stroke": "#3ca316"}'>8782,8484,8375,8298,7750,7356,6876,6088,6467,7053,7657,7483,8271,8106,7774,8171,8589,8321,8305,8002,8319,8493,8631,8980,8677,8496,8613,8080</span>
则:各字段解析如下:
doc.Find("table tbody tr").Each(func(i int, selector *goquery.Selection) {
var data CoinInfo
Rank := selector.Find("td").Eq(0).Text()
CoinName := strings.TrimSpace(selector.Find("td").Eq(1).Text())
CurrentCount := selector.Find("td").Eq(2).Text()
CurrentPrice := selector.Find("td").Eq(3).Text()
CurrentMark := selector.Find("td").Eq(4).Text()
Count := selector.Find("td").Eq(5).Text()
Change := strings.TrimSpace(selector.Find("td").Eq(6).Text())
不懂的可以看看goquery 函数方法,结合网页源代码一起看。
Data, _ := json.MarshalIndent(allData, "", " ")
fmt.Println(string(Data))
全部代码:注意核心代码很少
type CoinInfo struct {
Rank string `json:"rank"`
Name string `json:"name"`
CurrentCount string `json:"current_count"`
CurrentPrice string `json:"current_price"`
CurrentMark string `json:"current_mark"`
Count string `json:"count"`
Change string `json:"change"`
}
func queryExampleTwo() {
doc, err := goquery.NewDocument("https://www.feixiaohao.com/")
if err != nil {
log.Fatal(err)
}
var allData []CoinInfo
doc.Find("table tbody tr").Each(func(i int, selector *goquery.Selection) {
var data CoinInfo
Rank := selector.Find("td").Eq(0).Text()
CoinName := strings.TrimSpace(selector.Find("td").Eq(1).Text())
CurrentCount := selector.Find("td").Eq(2).Text()
CurrentPrice := selector.Find("td").Eq(3).Text()
CurrentMark := selector.Find("td").Eq(4).Text()
Count := selector.Find("td").Eq(5).Text()
Change := strings.TrimSpace(selector.Find("td").Eq(6).Text())
data = CoinInfo{
Rank: Rank,
Name: CoinName,
CurrentCount: CurrentCount,
CurrentPrice: CurrentPrice,
CurrentMark: CurrentMark,
Count: Count,
Change: Change,
}
allData = append(allData, data)
})
Data, _ := json.MarshalIndent(allData, "", " ")
fmt.Println(string(Data))
}
结果:
[
{
"rank": "1",
"name": "BTC-比特币",
"current_count": "¥8,444亿 ",
"current_price": "¥50,091",
"current_mark": "1,686万",
"count": "¥4,413,172万",
"change": "-9.84%"
},
{
"rank": "2",
"name": "ETH-以太坊",
"current_count": "¥4,902亿 ",
"current_price": "¥5,025",
"current_mark": "9,755万",
"count": "¥1,749,536万",
"change": "-9.68%"
},
{
"rank": "3",
"name": "XRP-瑞波币",
"current_count": "¥2,335亿 ",
"current_price": "¥5.98",
"current_mark": "3,902,901万*",
"count": "¥1,765,933万",
"change": "-15.33%"
},
...
]
上文就是一个简易的爬虫示例,主要使用的是goquery 这个解析网页的第三方库的使用,更多的用法和其他的第三方库差不多,甚至你能看出各种编程语言的相通之处。
除此之外,希望你能更加理解:编程语言只是工具。这句话的含义。