计算房租收入比(2)- 100行代码采集招聘职位数据

本文作者 @东东哥。项目整体思路和最终结果展示参见文章:

东东哥:用Python爬了一线城市的房租与工资,一线城市的房租在工资的占比真的很高吗?

这一篇是对其中收入数据的获取做具体讲解。

上一篇:计算房租收入比(1)- scrapy 爬取网上租房信息

附代码:gitee.com/crossin/snipp

一、背景

为了分析一线城市的房价在工资的占比,我用Python分别爬取了自如以及拉勾的数据。前一篇文章用scrapy爬取了自如房源信息,本文接着爬取拉钩的信息。这次我们直接使用requests进行爬取。

数据预览:

watermark,image_bG9nby9jc2RuXzEucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLGhfNjI=,g_se,x_0,y_0,t_100

二、分析网页结构

拉勾url: lagou.com/jobs/list_/p-. 打开链接,观察网页,职位基本信息都可以看到,因此就不进入职位详情页爬取。点击“下一页”,发现网站的url并没有任何变化,说明整个职位信息都是通过Ajax得到的。所以接下来就是找出勾网的 ajax 请求地址传递参数得到 json 数据,并提取我们所需要的信息。2. 打开浏览器F12,进入开发者工具,选择Network,我们选择XHR(XmlHttpRequest)就可以选出Ajax的请求包,但是url比较多的话就不好找。所以将职位表中任一职位,复制到 2 中查找,双击 3 就可以得到 4,可以看到response中的数据就是以 json 保存的:

watermark,image_bG9nby9jc2RuXzEucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLGhfNjI=,g_se,x_0,y_0,t_100

3. 点击上图中的 preview可以看到职位信息在result中,且职位数totalcount有221202条,但是在翻页时我们最多只能翻到30页,所以需要先获得 totalcount 后求出页数,再进行抓取。

watermark,image_bG9nby9jc2RuXzEucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLGhfNjI=,g_se,x_0,y_0,t_100

4. 点进去就能看到header信息

watermark,image_bG9nby9jc2RuXzEucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLGhfNTQ=,g_se,x_0,y_0,t_100

watermark,image_bG9nby9jc2RuXzEucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLGhfNTQ=,g_se,x_0,y_0,t_100

5. 可以发现是一个post。request_url, 就是请求 ajax 文件的 url。formdata中可以看到, 请求参数有 first 测试后发现保持默认即可,pn 是页码数,kd 是关键词,可以是城市,职位,公司。

6. 观察 Cookie

watermark,image_bG9nby9jc2RuXzEucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLGhfNjI=,g_se,x_0,y_0,t_100

在 user_trace_token 中很容易看出 20200224125912 这部分是时间戳,后面的部分则是 UUID,所以拉勾的cookie 是不断变化的,不能直接复制浏览器中的 cookie。

我采用的方法是先请求这个URL:lagou.com/jobs/list_/p-,携带返回的 cookie,再去请求请求 ajax 文件的 url

代码

def get_url(keyword,pn):
    # 浏览器地址栏显示的url
    web_url = "https://www.lagou.com/jobs/list_/p-city_0?px=new" 
    # ajax 请求地址
    headers_url = "https://www.lagou.com/jobs/positionAjax.json?px=new&needAddtionalResult=false"

    headers = {"Accept": "application/json, text/javascript, */*; q=0.01",
               "Referer": web_url,
               "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"
               }
    form_data = {
            "first": "true",
            "pn": "{}".format(pn),
            "kd": "{}".format(keyword)
            }
    # 创建 cookie 对象
    session = requests.Session()
    # 发送请求,获得cookies
    session.get(url=web_url,headers=headers)
    # 传递 cookie
    response = session.post(url=headers_url, headers=headers, data=form_data)

    return response

到这里,爬拉勾的难点就已经没有了,接下来从 JSON 中提取我们需要的信息就ok了。

三、代码实现

1. 导入相关库

import requests
import json
from tqdm import trange  # pip install trange 进度条
import pymysql
from pymysql import cursor

2. 得到总页数

def total_Count(response):
    html = response.json()
    # print(page)
    total_count = html['content']['positionResult']['totalCount'] # totalCount为总个数
    pn_count = int(total_count)//15 + 1
    # 页数
    print('职位总数{},共{}页'.format(total_count,pn_count))
    return pn_count

3. 提取数据,并存入MySQL数据库

dbparams = {
            'host': '127.0.0.1',
            'port': 3306,
            'user': 'root',
            'password': '1234',
            'database': 'lagou',
            'charset': 'utf8',
            'cursorclass': cursors.DictCursor
            }
def parse_url(response):
    # 创建连接
    con= pymysql.connect(**dbparams)
    with con.cursor() as cursor:   
        json_data = json.loads(response.text)
        results = json_data['content']['positionResult']['result']
        for result in results:
            info = {
                    "positionName" : result["positionName"],
                    "companyFullName" : result["companyFullName"],
                    "companySize" : result["companySize"],
                    "industryField" : result["industryField"],
                    "financeStage" : result["financeStage"],
                    "firstType" : result["firstType"],
                    "skillLables" :str(result["skillLables"]),
                    "positionLables" : str(result["positionLables"]),
                    "createTime" : result["createTime"],
                    "city" : result["city"],
                    "district" : result["district"],
                    "salary" : result["salary"],
                    "workYear" : result["workYear"],
                    "jobNature" : result["jobNature"],
                    "education" :result["education"],
                    "positionAdvantage" : result["positionAdvantage"]
                    }
            sql = """INSERT INTO info(Id, positionName, companyFullName,companySize,
                            industryField,financeStage,firstType,skillLables,positionLables,createTime,city,district,
                            salary,workYear,jobNature,education,positionAdvantage) 
                        VALUES (null,%s, %s, %s, %s, %s,%s, %s, %s, %s, %s,%s, %s, %s, %s, %s,%s)"""
            cursor.execute(sql, (info['positionName'],info['companyFullName'],
                    info['companySize'],info['industryField'],info['financeStage'],info['firstType'],info['skillLables'],
                    info['positionLables'],info['createTime'],info['city'],info['district'],info['salary'],
                    info['workYear'],info['jobNature'],info['education'],info['positionAdvantage']))
            con.commit()
        con.close()
        # 返回结果
        return results

4. 实现翻页

def main():
    # keyword = input('输入城市, 职位或公司, 如果为空,则代表全国各城市职位 \n') #输入搜索内容
    # 我将拉勾网包含的城市抓取下来,存在了city.txt文件中   
    file = open("city.txt",encoding='utf8')
    for city in file.readlines():  # 读取城市, 也可以注释掉这行代码,用关键词输入

        keyword=city.strip('\n')
        print(keyword)  
        response = get_url(keyword,pn=1)
        num = total_Count(response)  # 获得数据总个数和页数
        for i in trange(1,int(num)+1): # 实现翻页效果
            response = get_url(keyword, pn=i)
            results = parse_url(response)
            # 测试的时候发现可以得到的总页数,但是最多只能抓取到200页
            # 所以判断如果结果为空就结束循环
            # print(results)
            if results == []:
                break

四、总结

网上说有封 IP 的现象,但是我没遇到,爬取的时候也没有设置延迟,只是一个关键词下的职位最多只能爬取200页。整个过程相对容易,我爬了拉钩网中所有城市,一共6w+数据。速度是有点慢,有兴趣的可以自己改成多线程,或者用 scrapy 实现。

附代码:gitee.com/crossin/snipp

------

欢迎搜索及关注:Crossin的编程教室

这里还有更多精彩。一起学,走得远

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值