Python和Beautifulsoup爬虫的应用-前程无忧

Python 爬虫实践

  • 目标
  • 环境搭配
  • 难点
    • 学校名称匹配
    • 薪酬单位
  • 解决方案
    • 学校名称匹配
    • 薪酬单位
  • 最终数据
  • 爬虫源代码(不包含数据清理)
  • 结语

目标

爬取前程无忧北上广深各国际学校招聘信息,统计一线城市国际学校员工(老师,非老师)薪酬水平。可用数据实际不够准确,数量很少,这里只是提供一套demo进行一遍操作。原始数据如下:
Python和Beautifulsoup爬虫的应用-前程无忧_第1张图片

环境搭配

  • Useful Packages
    1. requests,与服务器建立连接
    2. beautifulsoup, 抓取网页信息
    3. xlwt,可将所爬取数据存入Excel
    4. pandas, numpy 数据清理
    5. plotnine python里调用R语言的可视化包ggplot
  • Anaconda - Jupyter Notebook

难点

这里不想过多说怎么具体爬取页面,网上有很多类似例子并不难,最后页我也附录了爬虫代码。主要讲一下爬取这类招聘网站所遇到的难点。

学校名称匹配

  • 其实只是单一的爬取数据并不复杂,网上有很多共享代码。那么问题来了!第一,如果规定好了几所国际学校,所爬取数据应该只包含这几所国际学校;第二;由于招聘网站上录入学校名称并不一定完全和真正的名称一致,从而导致错失了一部分数据,例如‘深圳益田国际学校’有可能在招聘网站上显示为‘深圳益田国际部‘,但其实两者一样。 程序并不会帮你自动区分其中区别。

薪酬单位

  • 薪酬不统一。原始数据中,薪酬被分为(万/月,万/年,千/月,元/天)。

解决方案

学校名称匹配

  • 利用正则表达也就是 regular expression 检索每一条所爬数据,如果符合条件则爬下来并储存,否则就跳过检索下一条。举个例子,前程无忧上某一条要爬数据显示学校名称为‘深圳益田国际部’ 我们可以通过建立一个字典dictionary 储存关键字‘益田’和‘国际’,从而省略检索最后一个‘部’使其同时可匹配学校两字。唯一不足是字典需要手动判断并输入关键字。代码如下:
# 交大可匹配:交大剑桥或者交大国际
d_guangzhou = {
			   '英国': '学校', '华南师范': '国际',
               '交大': '剑桥|国际', '第二外国语': '国际'
              }

for key, value in d_shenzhen.items():
	regexp_key = re.compile(r'{}'.format(key))   # 匹配第一个词
    regexp_value = re.compile(r'{}'.format(value)) # 匹配第二个词
	if regexp_key.search(company) and regexp_value.search(company): # 如果两个字同时存在于所检索的company中
		# Extact the data 

薪酬单位

  • 同样还是利用正则表达。匹配‘万千元’以及‘月年天’,统一薪酬单位为每月收入多少万。代码如下:
# 创建新的dataframe"薪水_万每月"

job["薪水_万每月"] = '' 

for i in range(len(job["薪水"])):
    
    str = job["薪水"][i]
    
    # 匹配类型有 :1.5—2万/月,6-8千/月,15-20万/年,120元/天
    regex = re.match('(((.+)-(.+))|(.+))([万千元])/([月天年])', str)
    
    if regex.group(7) == "月":
    
        if regex.group(6) == "万":

            m = [float(regex.group(3))*10000,float(regex.group(4))*10000]
            num = stats.mean(m)
            job["薪水_万每月"][i] = num

        elif regex.group(6) == "千":

            m = [float(regex.group(3))*1000,float(regex.group(4))*1000]
            num = stats.mean(m)
            job["薪水_万每月"][i] = num
        
    elif regex.group(7) == "年":
        
        y = [float(regex.group(3)),float(regex.group(4))]
        num = stats.mean(y) / 12 * 10000
        job["薪水_万每月"][i] = num
    
    else:   
    
        num = float(regex.group(1)) * 20
        job["薪水_万每月"][i] = num

最终数据

Python和Beautifulsoup爬虫的应用-前程无忧_第2张图片

爬虫源代码(不包含数据清理)

# -------------------------------- 部分代码转载于网络 -----------------------------------------
def get_html():

    k=1 #参数k代表存储到excel的行数
    wb = xlwt.Workbook()  # 创建工作簿
    f = wb.add_sheet("招聘信息")  # 创建工作表
    
    '''
    下方的循环是将Excel表格中第一行固定
    Excel表第一行的前五列分别对应 职位、公司、工作地点、薪水、发布日期
    '''
    
    raw = ['职位', '公司', '工作地点', '薪水', '发布日期']
    for i in range(len(raw)):
        f.write(0, i, raw[i])
        
        '''
        write函数中第一个参数表示存储到多少行
        第二各参数存储到多少列表,第三个参数代表存储到对应行列的值
        '''
        
    url='https://search.51job.com/list/040000,000000,0000,23,9,99,%2520,2,{}.html'
    
    try:
        
        for page in range(300): #解析前11页
            res = requests.get(url.format(page))
            res.encoding = 'gbk'
            
            if res.status_code == 200:
                
                soup = BeautifulSoup(res.text, 'lxml')
                t1 = soup.select('.t1 span a')
                t2 = soup.select('.t2 a')
                t3 = soup.select('.t3')
                t4 = soup.select('.t4')
                t5 = soup.select('.t5')
                
                for i in range(len(t2)):
                    
                    job = t1[i].get('title')#获取职位
                    href = t2[i].get('href')#获取链接
                    company = t2[i].get('title')#获取公司名
                    location = t3[i+1].text#获取工作地点
                    salary = t4[i+1].text#获取薪水
                    date = t5[i+1].text#获取发布日期
                    
                    for key, value in d_shenzhen.items():
                        
                        regexp_key = re.compile(r'{}'.format(key))
                        regexp_value = re.compile(r'{}'.format(value))
                        
                        if regexp_key.search(company) and regexp_value.search(company):

                            print(job + " " + company + " " + location + " " + salary + " " + date + " " + href)

                            f.write(k,0,job)
                            f.write(k,1,company)
                            f.write(k,2,location)
                            f.write(k,3,salary)
                            f.write(k,4,date)

                            k+=1

                        else:

                            continue
                            
            print(f"Page : {page}")
            
        wb.save('招聘_深圳_分割.csv')
        
    except TimeoutError:
        print("请求失败")
        return  None
    
if __name__=='__main__':
    get_html()

结语

大多数情况的爬虫其实所爬网站已经可以设定好关键字,但是有些情况下并不能完成我们所需的任务。正则表达是一个很好应用与此的技术,特别是在特定词句匹配方面。值得好好钻研。不足之处是字典的建立和关键词的决定需要人类来判断,希望有更好的匹配办法可以应用在类似这样的爬虫案例上。

你可能感兴趣的:(爬虫)