goquery爬虫Boss直聘信息

clown1995 · · 3521 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。


title: goquery爬虫Boss直聘信息
tags: go,goquery
author: Clown95


背景

Hello小伙伴们,在之前的文章中,我们对go的爬虫库goquery进行了简单的介绍,今天我们就来进行一个爬虫BOSS直聘Golang招聘信息的实战项目。


需求

在写代码之前,我们先了解下我们需要爬取什么内容。


招聘要求我们鼠标悬停在列表上,会出现一个悬浮窗里面有职位描述

根据网站给出的信息我们可以爬虫到以下内容:

  • 工作岗位
  • 薪资范围
  • 公司地址
  • 工作经验
  • 学历要求
  • 公司名称
  • 公司信息
  • 招聘要求

源文件说明

我们先看一个列表的HTML代码,了解我们需要爬取的内容在哪个标签。

<li>
     <div class="job-primary">
         <div class="info-primary">
             <h3 class="name">
                 <a href="/job_detail/6177f4eb544e15f81n172dm8GVI~.html" data-jid="6177f4eb544e15f81n172dm8GVI~" data-itemid="1" data-lid="1rzMXyp7wgw.search" data-jobid="19124190" data-index="0" ka="search_list_1" target="_blank">
                     <div class="job-title">Golang</div>
                     <span class="red">15k-30k</span>
                     <div class="info-detail"></div>
                 </a>
             </h3>
             <p>北京 朝阳区 四惠<em class="vline"></em>3-5年<em class="vline"></em>本科</p>
         </div>
         <div class="info-company">
             <div class="company-text">
                 <h3 class="name"><a href="/gongsi/a40445e10ec47e2b1Xx83tm-.html" ka="search_list_company_1_custompage" target="_blank">元征科技</a></h3>
                 <p>互联网<em class="vline"></em>已上市<em class="vline"></em>1000-9999人</p>
             </div>
         </div>
         <div class="info-publis">
             <h3 class="name"><img src="https://img.bosszhipin.com/beijin/mcs/useravatar/20180828/41c31311d7c965b71e51ad58a3be8eca6a4d2e0010b6eada6c207131ca360c65_s.jpg?x-oss-process=image/resize,w_40,limit_0" />罗女士<em class="vline"></em>HRBP</h3>
             <p></p>
         </div>
         <a href="javascript:;" data-url="/gchat/addRelation.json?jobId=6177f4eb544e15f81n172dm8GVI~&lid=1rzMXyp7wgw.search" redirect-url="/geek/new/index/chat?id=9e2e5060ec68738a1X1729y4EVQ~" target="_blank" class="btn btn-startchat">立即沟通
         </a>
     </div>
 </li>

通过上面的代码我们可以看到:

  • 工作岗位是在div class="info-primary"下面的div class="job-title"

  • 薪资范围是在div class="info-primary"下面的span class="red"

  • 公司地址+工作经验 +学历要求是在div class="info-primary"下面的p标签

  • 公司名称是在div class="info-company"下面的h3 标签class="name"

  • 公司信息是在div class="info-company"下面的p标签

  • 招聘要求是Json接口有两种方法一是可以直接获取a标签中的json,而是获取a标签中的data-jid属性和data-lid属性拼接json

代码编写

  1. 浏览器的User-age设置

大部分网站都具备一定的反爬虫能力,最简单的就是判断访问网页的客户端是否是浏览器,所以我们现在需要模拟下浏览器的User-Agent

//常见浏览器的User-Agent
var UserAgentList = []string{"Mozilla/5.0 (compatible, MSIE 10.0, Windows NT, DigExt)",
    "Mozilla/4.0 (compatible, MSIE 7.0, Windows NT 5.1, 360SE)",
    "Mozilla/4.0 (compatible, MSIE 8.0, Windows NT 6.0, Trident/4.0)",
    "Mozilla/5.0 (compatible, MSIE 9.0, Windows NT 6.1, Trident/5.0,",
    "Opera/9.80 (Windows NT 6.1, U, en) Presto/2.8.131 Version/11.11",
    "Mozilla/4.0 (compatible, MSIE 7.0, Windows NT 5.1, TencentTraveler 4.0)",
    "Mozilla/5.0 (Windows, U, Windows NT 6.1, en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
    "Mozilla/5.0 (Macintosh, Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
    "Mozilla/5.0 (Macintosh, U, Intel Mac OS X 10_6_8, en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
    "Mozilla/5.0 (Linux, U, Android 3.0, en-us, Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13",
    "Mozilla/5.0 (iPad, U, CPU OS 4_3_3 like Mac OS X, en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
    "Mozilla/4.0 (compatible, MSIE 7.0, Windows NT 5.1, Trident/4.0, SE 2.X MetaSr 1.0, SE 2.X MetaSr 1.0, .NET CLR 2.0.50727, SE 2.X MetaSr 1.0)",
    "Mozilla/5.0 (iPhone, U, CPU iPhone OS 4_3_3 like Mac OS X, en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
    "MQQBrowser/26 Mozilla/5.0 (Linux, U, Android 2.3.7, zh-cn, MB200 Build/GRJ22, CyanogenMod-7) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"}

//从上面列表中随机获取一个User-Agent
func GetRandomUserAgent() string {
    r := rand.New(rand.NewSource(time.Now().UnixNano()))
    return UserAgentList[r.Intn(len(UserAgentList))]
}
  1. 获取网页

我们爬虫的第一步就是先要获取目标页面的源代码。


func GetHtml(bossurl string) *http.Response {

    proxyurl := "http://122.136.212.132:53281"  //代理IP,需要自己更换

    proxy, _ := url.Parse(proxyurl)  // 解析代理IP

    netTransport := &http.Transport{  //要管理代理、TLS配置、keep-alive、压缩和其他设置,可以创建一个Transport
        Proxy:                 http.ProxyURL(proxy),
        MaxIdleConnsPerHost:   10,
        ResponseHeaderTimeout: time.Second*2,  //超时设置
    }

    client := &http.Client{  //要管理HTTP客户端的头域、重定向策略和其他设置,创建一个Client
        Timeout:   time.Second * 2,
        Transport: netTransport,
    }
    req, err := http.NewRequest("GET", bossurl, nil) //NewRequest使用指定的方法、网址和可选的主题创建并返回一个新的*Request。

    if err != nil {
        log.Println(err)
    }
    
        req.Header.Add("User-Agent", models.GetRandomUserAgent()) //模拟浏览器User-Agent
    resp, err := client.Do(req) //Do方法发送请求,返回HTTP回复
    if err != nil {
        log.Println(err)
    }

    return resp  //返回网页响应

}

可以看到代码中,通过http.Transpor添加了代理IP,并且设置了超时时间。接着通过http.Client创建了一个客户端设置代理IP。为什么需要添加代理IP呢?这是为了防止我们本机的IP,因为访问目标网站过多而被拉黑。简单的来说也是防反爬虫的一种必备方法,我们的代码中只使用了一个代理仅作为演示。在实际开发中,你应该拥有一个代理池能够验证代理的有效性,并随机更换代理。

  1. 解析网页内容

网页内容的解析是我们程序的核心,我们使用GoQuery遍历的匹配我们需要的信息。因为使用方都一样,在这边我们侧重说下招聘需求的解析。

func ParseHtml(resp *http.Response){
    defer resp.Body.Close()
    dom, err := goquery.NewDocumentFromReader(resp.Body)
    if err != nil {
        log.Fatalln(err)
    }

    dom.Find(".job-primary").Each(func(i int, selection *goquery.Selection) {
        time.Sleep(3 * time.Second)                                                   //防止访问次数过于频繁
        fmt.Println("公司名称:", selection.Find(".info-company .name").Text())            //公司名称
        fmt.Println("公司简介:", selection.Find(".info-company .company-text p ").Text()) //公司简单信息
        fmt.Println("招聘岗位:", selection.Find(".info-primary .job-title").Text())       //招聘岗位
        fmt.Println("简单信息:", selection.Find(".info-primary p").Text())                // 公司地址+ 工作经验+ 学历要求
        fmt.Println("薪资范围:", selection.Find(".info-primary .red").Text())             // 薪资
        data_lid, _ := selection.Find(".info-primary a").Attr("data-lid")
        data_jid, _ := selection.Find(".info-primary a").Attr("data-jid")
        jobJson := fmt.Sprintf("https://www.zhipin.com/wapi/zpgeek/view/job/card.json?jid=%s&lid=%s", data_jid, data_lid)

        fmt.Println("招聘要求:", GetJobInfo(jobJson))
        fmt.Println()

    })
}

这段代码可以看出,我们的程序是首先获取到json的两个参数信息data_jiddata_lid,然后拼接成一个完成的json接口。GetJobInfo()函数还未给出,我们稍后在看。

我们随便打开一个josn地址复制内容到json.cn解析下,可以看到主要的信息还是一个html。

因此我们先定义一个结构体用来解析json

type JsInfo struct {
    Code    int    `json:"code"`
    Message string `json:"message"`
    ZpData  struct {
        HTML string `json:"html"`
    } `json:"zpData"`
}

然后我们在封装一个GetJobInfo()函数进行Json内容的截取。因为json的主要内容是个html信息,所以我们仍然使用GoQery进行爬取。

func GetJobInfo(url string) (string) {
    respjson, _ := http.Get(url)
    resp_byte, _ := ioutil.ReadAll(respjson.Body)
    respHtml := string(resp_byte)
    var job models.JsInfo
    json.Unmarshal([]byte(respHtml), &job)
    dom, err := goquery.NewDocumentFromReader(strings.NewReader(job.ZpData.HTML))
    if err != nil {
        fmt.Println(err)
    }
    var s string
    dom.Find(".detail-bottom-text").Each(func(i int, selection *goquery.Selection) {
        s = selection.Text()

    })
    return s
}
  1. 主函数

主函数的内容比较简单,因为BOSS直聘的翻页跳转是通过ur实现的,我们通过for循环遍历10页的内容,并且添加sleep函数,防止访问过于频繁从而导致我们的IP被拉黑。

func main() {

    for page := 1; page < 10; page++ {
        bossurl := fmt.Sprintf("https://www.zhipin.com/c101010100-p100116/?page=%d&ka=page-%d", page, page)
        time.Sleep(3*time.Second) // 增加延时防止网站拉黑IP
        resp :=GetHtml(bossurl)
        ParseHtml(resp)
    }

}

总结

我们的爬虫小实战到此就完成了,为了防止IP被拉黑,我没有使用并发,有兴趣的小伙伴可以改善下我们的代码。我必须要再次强调,我们在爬虫的时候一定要设置代理IP,因为大部分网站都设置了反爬虫机制,如果我们IP在同一时间内访问次数过多,我们真实的IP会被网站运营商短暂或者永久性拉黑,这会影响到其他用户对网站的正常使用。

最后我们我们看下运行结果。


tip:如果需要北京golang招聘信息的小伙伴可以私信我们哦。


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:clown1995

查看原文:goquery爬虫Boss直聘信息

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

3521 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传