拉勾网职位数据爬取--按公司规模爬取

全部的代码见我的GitHub


这里改进了一下之前文章-拉勾网职位数据爬取,由于拉勾网最多只会显示30页的职位信息,为了获取更多的职位信息,就要分类爬取。


由于北京的Python职位很多,超过了30页的部分就不显示了,我为了能够比较全的爬取数据,就进行了分类爬取。这里我选择公司规模这个类别:

 小于15人  15-50人  50-150人  150-500人  500-2000人  2000人以上

这个类别不会重复,而且每个小类下的数据也不会超过30页。

类别分析

这个类别不同体现在URL上,下面是小于15人的URL:

https://www.lagou.com/jobs/positionAjax.json?px=default&gm=%E5%B0%91%E4%BA%8E15%E4%BA%BA&city=%E5%8C%97%E4%BA%AC&needAddtionalResult=false&isSchoolJob=1

其中gm=%E5%B0%91%E4%BA%8E15%E4%BA%BA就是小于15人

下面是全部类别的公司规模部分的网址:

小于15人 gm=%E5%B0%91%E4%BA%8E15%E4%BA%BA
15-15人 gm=15-50%E4%BA%BA
50-150人 gm=50-150%E4%BA%BA
150-500人 gm=150-500%E4%BA%BA
500-2000人 gm=500-2000%E4%BA%BA
2000人以上 gm=2000%E4%BA%BA%E4%BB%A5%E4%B8%8A

页数分析

总页面数其实在POST请求后发回来的JSON数据中。

result['content']['positionResult']['totalCount']

代码实现

循环公司规模这个类别,然后在每个分类下找到页面数,然后用之前写好的方法进行爬取。

import requests
from fake_useragent import UserAgent
from lxml import etree
import csv
import json
import time
import pandas as pd

请求头Headers、表单Form Data补全

请求头是为了反反爬虫的,表单是用来POST请求时提交的。

Host = "www.lagou.com"
Origin =  "https://www.lagou.com"
Referer = "https://www.lagou.com/jobs/list_Python?px=default&gx=&isSchoolJob=1&city=%E6%9D%AD%E5%B7%9E"
ua = UserAgent()

headers = {
    'User-Agent':ua.random,
    'Host':Host,
    'Origin':Origin,
    'Referer':Referer
}

data= {
    'first': False,
    'pn': "1",
    'kd': 'Python'
}

URL构造

下面的URL中的gm部分被替换为{},后面根据类别来补全。

url = "https://www.lagou.com/jobs/positionAjax.json?px=default&gm={}&city=%E5%8C%97%E4%BA%AC&needAddtionalResult=false&isSchoolJob=1"

类别字典

下面是公司规模的类别字典列表。这是用来补全到URL的gm参数中的。

gm_list = [{'class':'小于15人','url':'%E5%B0%91%E4%BA%8E15%E4%BA%BA'},
           {'class':'15-50人','url':'15-50%E4%BA%BA'},
           {'class':'50-150人','url':'50-150%E4%BA%BA'},
           {'class':'150-500人','url':'150-500%E4%BA%BA'},
           {'class':'500-2000人','url':'500-2000%E4%BA%BA'},
           {'class':'2000人以上','url':'2000%E4%BA%BA%E4%BB%A5%E4%B8%8A'}]

职位信息、总页数获取函数

def getPosition(url,headers,data,page):

    data['pn'] = str(page)
    response = requests.post(url,headers = headers,data = data)
    print(response.status_code)
    result = response.json()
    if result['success']:
        print("正常获取")
        position = result['content']['positionResult']['result']
        totalCount = result['content']['positionResult']['totalCount'] #返回的职位总数(用来计算页数)
        pageCount = int(totalCount)//15 + 1 #每页15条职位,这里向下整除15
        time.sleep(1)  # 获取正常的情况下延时1s请求一次
        return position,pageCount
    else:
        print("您操作太频繁,请稍后再访问")
        time.sleep(10)  # 出现异常时,间隔10s后再获取
        position,pageCount = getPosition(url,headers,data,page) #递归获取
        return position,pageCount

主函数

这里通过循环整个类别字典来依次爬取对应类别的全部职位信息。主要就是:

for gm in gm_list:
    gm_url = url.format(gm['url'])
    ...
    #对应类别的职位信息爬取过程
    ...
    #下面是保存到csv文件
    total_df.to_csv('Python-School-Beijing-{}.csv'.format(gm['class']), sep = ',', header = True, index = False)   
for gm in gm_list:
    gm_url = url.format(gm['url'])

    #下面是寻找“总页面”(pageCount)的过程
    position,pageCount = getPosition(gm_url,headers,data,page = 1)
    #下面是初始化total_df过程
    df = pd.DataFrame(position)
    total_df = df

    #如果只有一页,那么直接得到了所有的职位数据total_df
    if pageCount > 1:
        for page in range(2,pageCount+1): #注意:第一页的数据已经存储起来了,这里从第二页开始
            position,_ = getPosition(gm_url,headers,data,page)
            df = pd.DataFrame(position)
            total_df = pd.concat([total_df,df],axis = 0)

    #下面输出一定信息到控制台
    print("{}".format(gm['class']) + '\n' + '总页数为:' + str(pageCount))
    total_df.info()
    #下面是保存到csv文件
    total_df.to_csv('Python-School-Beijing-{}.csv'.format(gm['class']), sep = ',', header = True, index = False)

全部的代码见我的GitHub

猜你喜欢

转载自blog.csdn.net/dta0502/article/details/82115769