大家好, 我是谢伟, 一名程序员之前接触的语言是 Python, 编程领域学会的第一个技能是爬虫, 凭借着爬虫技术先后在两个创业公司从事的是网络爬虫这份活
研究生毕业后, 基于各方面的考虑, 选择的是现在的这份工作主要的是从事云计算方面的工作, 再细化点, 主要从事云计算中的 PaaS 部署相关的工作
目前正在着手的任务是开发一款命令行工具支持 PaaS 部署相关的各种命令, 且开发语言是 go
我熟悉的是 Python , 借着之前的编程基础, 顺利的转到了 go 语言很自觉的会比较两款语言的相似和不同之处同时我越来越理解到: 编程语言只是工具这句话的含义
编程语言只是工具
编程最重要的是逻辑, 不管是什么领域的开发, 逻辑才是最重要的所以架构师这一职业, 对逻辑的要求就很高, 他需要技术选型方案设计方案评估等一系列技能
编程只是实现或者验证方案是否合适
逻辑很重要
示例很重要
这是我从 Python 转而学习 go 语言中总结出来的经验为了了解各种各样的 go 语言的特性, 我有一个工程专门用来进行 go 编程语言示例的学习即: 想要验证一个库或者函数的时候, 达到你需要的效果, 最好的方法是进行最小示例的验证
比如: 之前开发命令行工具需要支持查询命令表格显示这一功能就不断的使用示例的学习方法快速上手, 快速开发
快速上手
企业需要的职员是来干活的, 需要产出价值, 完成任务的并没有过多的时间让你学习需要的是快速上手的能力前期可以有短暂的输入时间之后需要边输入边产出快速上手, 实现价值交付
不断的修改
编程不可能一步到位, 除非你是传说中的编程天才代码需要不断的修改, 修改的同时对编程语言各种熟悉, 同时需要不断的完善代码, 能复用的就复用函数应该是编程中最常见的了, 函数不能编写过长凡是稍微有点处理动作的都应该独立出一个函数进行复用主函数的处理动作应该是越简单明了越好不管是以后重构还是增加功能都能很好的实现
学习各种编程思想
随着系统的越来越复杂, 一定需要学习软件行业先进的编程思想, 解决复杂的问题, 比如 DDD (领域驱动开发), TDD(测试驱动开发)..., 这是我下一个的研究点...
总结很重要
内部是会有各种各样的会议: 计划会总结会迭代会复盘会..., 等等, 所以导致一天其实真正的开发时间并不是很多, 其中还会被各种各样的干扰而导致中断, 最终的编程效率其实不是很高, 自身除了需要进行合理的时间管理之外, 我觉得总结很重要, 这些会一般是针对团队的, 你需要和自己真正的扯上关系才能不断的成长, 比如: 迭代总结会, 通常是分析团队的任务的完成率, 做的好的地方和不好的地方, 针对你个人你也应该不断的总结自己好的地方和不好的地方, 不然, 时间过的很快, 嗖的一下几年过去了, 得不到应有的成长
言归正传: 下面使用 go 语言实现一个简单的爬虫已经有了 python 爬虫技能, 为什么需要进行 go 爬虫的实现版? 为了更加的熟悉 go 的语言特性
我们已经知道: 一个简易的标准爬虫的步骤是
HTTP 获取网页内容
进行网页内容解析
对解析的内容进行处理
获取网页内容:
使用 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"`
- }
获取网页内容
- net / http 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
- }
goquery : 解析网页的库
第三方库, 需要自己安装
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 函数方法, 结合网页源代码一起看
json 格式输出
- 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%"
- },
- ...]
来源: http://www.jianshu.com/p/e391b7b61c9a