找到中国电信中的数学

最近正是 2023 届秋招的时候. 作为计算数学专业的研究生, 我在找工作时发现选择是如此之少, 每天要浏览大量的招聘网站和岗位信息. 昨天打开中国电信的招聘网站, 发现它有大量的分公司, 每个分公司又有大量的子分公司, 每个子分公司又有大量的岗位. 一个个点来, 却鲜少找到其中的数学. 心生悲哀, 所以想写一个爬虫, 让我们来找找电信中的数学.

访问每个分公司

首先我们点进中国电信 2023 校招的网站.
在这里插入图片描述

随便点击一个分公司, 可以看到地址栏出现了两个 id 的数值.
在这里插入图片描述

根据以往的经验, 这个数值的变化应该就会导向不同的分公司. 测试一下, 果然如此. coid 的后三位变化对应不同的分公司.

那么访问每个分公司的代码就已经写好了:

url = "http://campus.51job.com/chinatelecom2023/jobdetail.html?ctmid=6271848&type=1&coid=7324" + str(companyIdx)

companyIdx 跑起来, 就可以依次访问每个分公司的招聘网址了.

访问每个子分公司

下面我们再看一看各个分公司的子分公司.
在这里插入图片描述

失望地发现, 子分公司改变不会带来网址的变化, 也就是说这个网页是动态加载的. 一个直观且方便的方法是使用 selenium 模拟点击, 获得对应的页面. 为此, 我们打开浏览器的开发者模式, 检查一下我们应该点击网页的什么模块.

按 F12 打开开发者模式, 在 elements(元素) 标签按 ctrl+F 搜索延边分公司, 定位到它的类为 divItem:
在这里插入图片描述

那么接下来的代码就很清楚了:

try: 
    browser = webdriver.ChromiumEdge(options=edge_options)
    browser.get(url)
    subCompanies = browser.find_elements("class name", "divItem")
    for subComp in subCompanies:
        # 点击进入当前子分公司, 点开所有职位
        subComp.click() 
        time.sleep(2)
        pass  # 这里展开每个岗位的信息
except Exception:
    return None

展开每个岗位信息

再看一下每个岗位的信息, 发现它们和子分公司一样是动态的, 那我们也模拟点击一下. 同样, 我们去查看一下应该点击什么元素:
在这里插入图片描述

jobList = browser.find_elements("class name", "listName")
for job in jobList:
    job.click()
    time.sleep(0.3)

现在我们把当前分公司的每个岗位都展开了, 接下来就可以用处理静态网页的方法查找抓取我们想要的信息了:

html = browser.page_source

查找里面的数学

查找网页的元素可以用 BeautifulSoup, 当然也可以直接用正则表达式. 这里我们就用正则表达式写一下吧. 我们先研究一下我们想要获得什么样的信息.

首先回顾我们一开始的目的就是爬取所有招聘专业有数学的岗位, 这就给了一个清晰的限制:

  1. 要匹配一个描述岗位信息的 element;
  2. 岗位信息里要有 “数学”, “数学类”, “专业” 这样的限定词.

研究一下网页源码:
在这里插入图片描述

可以看见展开后的描述岗位信息的源码放在 <div class="listBottom actList"> 这块元素里了.

接下来我们再把岗位名字和单位名字匹配出来, 这就是我们想要的结果了.

pattern = re.compile('<div class="listBottom actList">.*?岗位\ *(.*?)\ *.*?<br.*?单位\ *(.*?)\ *.*?<br.*?数学.*?</div>', re.S)
jobs = re.findall(pattern, html)

记录带数学的岗位信息

然后打开一个文件把获取到的信息写进去即可.

def writeToFile(jobInfo):
    """写入岗位信息"""
    print("writing now \n")
    with open('./containMathJobs.txt', 'a', encoding='UTF-8') as f:
        f.write(json.dumps(jobInfo, ensure_ascii=False) + '\n')
        f.close()
    return

总结

更进一步, 应该用多线程多进程来加速一下. 但这里就不搞了, 只爬几个省份的话也用不了多久.

总结一下,

  1. 先获取访问各分公司网址的规则,
  2. 再模拟点击展开每个分公司的各个子分公司的各个岗位,
  3. 在此时的网页源码中匹配想要的信息
  4. 把获取到的信息保存到文件中

代码

import re
from selenium import webdriver
from selenium.webdriver.edge.options import Options
import time
import json


def getSubCompanies(url):
    """查找当前分公司的所有子分公司, 生成展开职位的列表"""
    try: 
        browser = webdriver.ChromiumEdge(options=edge_options)
        browser.get(url)
        subCompanies = browser.find_elements("class name", "divItem")
        for subComp in subCompanies:
            # 点击进入当前子分公司, 点开所有职位
            subComp.click()  
            time.sleep(2)
            jobList = browser.find_elements("class name", "listName")
            for job in jobList:
                job.click()
                time.sleep(0.3)
            html = browser.page_source
            yield html        
    except Exception:
       return None
       
def findMathIn(html):
    """找到想要的岗位信息"""
    pattern = re.compile('<div class="listBottom actList">.*?岗位\ *(.*?)\ *.*?<br.*?单位\ *(.*?)\ *.*?<br.*?数学.*?</div>', re.S)
    jobs = re.findall(pattern, html)
    for jobInfo in jobs:
        yield {
            "招聘岗位":jobInfo[0],
            "用人单位":jobInfo[1]
        }

def writeToFile(jobInfo):
    """写入岗位信息"""
    print("writing now \n")
    with open('./containMathJobs.txt', 'a', encoding='UTF-8') as f:
        f.write(json.dumps(jobInfo, ensure_ascii=False) + '\n')
        f.close()
    return

def main(companyIdx):
    url = "http://campus.51job.com/chinatelecom2023/jobdetail.html?ctmid=6271848&type=1&coid=7324" + str(companyIdx)

    subCompPages = getSubCompanies(url)
    for html in subCompPages:
        jobsInfos = findMathIn(html)
        for job in jobsInfos:
            writeToFile(job)
    
if __name__ == "__main__":

    # 设置参数
    edge_options = Options()

    # 关闭图形界面
    edge_options.add_argument("--headless")
    edge_options.add_argument("--disable-gpu")

    # # 反反爬青春版
    # edge_options.add_experimental_option('excludeSwitches', ['enable-automation'])
    # edge_options.add_argument('--disable-blink-features=AutomationControlled')

    for companyIdx in range(396, 497):  # 没有必要. 还是先有个想去的城市再选岗位吧? 
        main(companyIdx)
  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值