项目说明
本项目主要讲述如何爬取前程无忧的招聘信息,通过设定的关键词与地点来搜索站内的招聘信息并实现数据爬取,这是项目的爬虫功能需求。具体说明如下:
- 在浏览器访问 51Job 官方网站(https://www.51job.com/),并在搜索框输入关键词“Python”,地点选为“广州”,单击“搜索”按钮进入搜索页。
- 在搜索页中,所有符合条件的职位信息以列表的形式排序并设有分页显示。每条职位信息是一个 URL 地址,通过 URL 地址可以进入该职位的详情页。
- 职位详情页也是数据爬取的页面,爬取的数据信息有:职位名称、企业名称、待遇、福利及职位要求等。 项目的开发工具选择 Net/HTTP 和 goquery 实现爬虫开发与数据清洗,数据存储选择 gorm 框架,数据库选择 MySQL。
使用谷歌浏览器分析 51job——获取城市编号
项目开发是从搜索页开始,观察搜索页的 URL 地址可以发现,URL 含有关键词“Python”和多个数字编号,这些数字编号可能代表某些搜索条件。为了进一步验证这些数字编号的作用,将关键词保持不变,尝试切换不同的地点,比如地点分别选为“广州”、“北京”和“上海”,如图所示。
根据图中的 URL 地址及网页内容的变化,可以总结出两个关键点:
- 当选择不同地点的时候,网页的 URL 地址都会发生变化,从而导致网页内容随之变化,这说明网页内容是通过网站的服务器后台生成的,并非由 Ajax 实现数据动态渲染。
- 在 URL 地址的“list”后面,首个数字编号代表职位所在的地点,并且每个地方的数字编号都固定不变。
为了得到全国各个城市的数字编号,在浏览器的开发者工具里,单击“Network”选项卡并刷新搜索页,重新捕捉搜索页的请求信息。查看每个请求信息的响应内容,从中查找每个城市的数字编号,最终在“JS”选项卡下找到全国的城市编号,如图所示。
由上述分析可知,只要对图上的请求地址发送 HTTP 请求即可获取每个城市的数字编号,并将该请求的响应内容转换成字典格式,再将字典的键值进行互换。由于爬虫是根据使用者输入城市名来获取相应的数字编号,再通过城市编号构建相应的 URL 地址,所以将字典的键值进行互换可方便数字编号的获取。将城市的数字编号获取功能定义为函数 GetCityCode,函数的具体代码如下:
package main
import (
"encoding/json"
"fmt"
"github.com/axgle/mahonia"
"io/ioutil"
"net/http"
"strings"
)
//使用第三方mahonia实现网页内容的转码
func ConvertToString(src string, srcCode string, tagCode string) string {
srcCoder := mahonia.NewDecoder(srcCode)
srcResult := srcCoder.ConvertString(src)
tagCoder := mahonia.NewDecoder(tagCode)
_, cdata, _ := tagCoder.Translate([]byte(srcResult), true)
result := string(cdata)
return result
}
func GetCityCode(name string) string {
client := &http.Client{}
urls := "https://js.51jobcdn.com/in/js/2016/layer/area_array_c.js"
req, _ := http.NewRequest("GET" ,urls, nil)
resp, _ := client.Do(req)
//读取响应内容
body, _ := ioutil.ReadAll(resp.Body)
//设置响应内容的编码格式
results := ConvertToString(string(body), "gbk", "utf-8")
// 清洗响应内容,使其符合json格式要求
results = strings.Split(results, "=")[1]
results = strings.Split(results, ";")[0]
// 将清洗后的字符串转换为map数据格式
r := make(map[string]interface{})
json.Unmarshal([]byte(results), &r)
// 根据参数获取对应的城市编码
var result string
for k, v := range r{
if v == name {
result = k
}
}
return result
}
func main(){
a := GetCityCode("北京")
fmt.Print(a)
}
运算上述代码,将“北京”的城市名作为函数 GetCityCode 的参数,查看函数返回值是否为北京的城市编号,如图所示。