P

Python程序设计—scrapy爬虫与数据处理

古月 2024-01-06

需求分析

1.使用scrapy框架,抓取北京邮电大学、西安电子科技大学,自2023年11月1日以来的就业帖子。获取字段包括:招聘主题、发布日期、浏览次数。各存储为1个csv文件,名字分别为:BEIYOU_1、XIDIAN_1。

  1. 编写程序,遍历2个文件,对2个文件的数据做如下处理。
  • 去掉招聘主题两端的空格等无关字符(如空格、tab、换行等)。
  • 统一把日期处理为:YYYY-MM-DD的格式。
  • 统一把访问次数为空的置为0,字符串统一转为整数格式。

3.预处理完成的结果,存入一个Excel中,Excel包括2个标签页,分别为:北邮、西电。 标签页表头字段一致,包括:序号(数字序号)、招聘主题、发布日期、浏览次数。选中列设定对应列的数据类型:文本、文本、日期(YYYY-MM-DD)、数字(整数)。

4.人工对于前述Excel进行分析:

  • 最受北邮学生关注的招聘TOP10、最受西电学生关注的招聘TOP10(以浏览次数决定排序)。
  • 最受两校关注的招聘主题TOP10(在两个高校都出现,并且按浏览次数排序;只考虑帖子同名, 不用解析企业名称)。

系统设计

1.针对需求设计scrapy框架

分别观察西安电子科技大学就业信息网和北京邮电大学就业资讯网的特点,分别设计爬虫框架。

西电scrapy框架:

观察发现西电就业信息网的网页呈现为常规呈现,页面的定位也是由固定规律的url确定,这里我们使用固定规则生成西电就业信息网的页面url列表,作为start_urls放入爬虫框架进行响应:

base_url = "https://job.xidian.edu.cn/campus/index?domain=xidian&city=&page={}"

class MySpider(scrapy.Spider):
    name = "bupt_school"
    allowed_domains = ["job.xidian.edu.cn"]
    page_urls = [base_url.format(page) for page in range(1, 100)]
    start_urls = page_urls

对页面的响应信息进行分析,获取其中就业信息贴的href,并拼接为完整的url,放入回调函数进行请求,并将请求处理转向处理就业贴的parse_post函数:

    def parse(self, response):
        news_items = response.css('.infoBox.campus-index-front-list .infoList')
        for news_item in news_items:
            href = news_item.css('li.span7 a::attr(href)').get()
            full_url = urljoin(response.url, href)
            item = BuptSchoolItem()
            yield scrapy.Request(url=full_url, callback=self.parse_post, meta={'item': item})

针对就业贴的页面设计,提取所需的信息并放入scrapy处理,这里我们使用了xpath进行筛选,而后续的北邮爬虫,我们使用了css进行筛选,同时,我们根据得到的日期信息进行爬虫停止的条件设置。此外,我们考虑后续我们要对数据进行合并,就业信息贴名称完全一致的可能性较小,所以我们同时获取了招聘发布单位名称:

    def parse_post(self, response):
       item = BuptSchoolItem()
        item['tittle'] = response.xpath('/ html / body / div[1] / div[3] / div[2] / div / div[1] / div / div[1] / h5/text()').get()
       item['employer'] = response.xpath('/html/body/div[1]/div[3]/div[2]/div/div[1]/div/div[1]/a/text()').get()
        time_text=response.xpath('/html/body/div[1]/div[3]/div[2]/div/div[1]/div/div[2]/div/ul/li[1]/text()').get()
        time_match=re.search(r'(\d{4}-\d{2}-\d{2})', time_text)
        if time_match:
            date = time_match.group(1)
            if date == '2023-10-31':  # 如果日期满足条件
                self.log(f"匹配到日期:{date},停止循环处理")
                raise scrapy.exceptions.CloseSpider('DateMatched')  # 停止爬虫
            item['time'] = date
      views_text=response.xpath('/html/body/div[1]/div[3]/div[2]/div/div[1]/div/div[2]/div/ul/li[2]/text()').get()
        views_match= re.search(r'(\d+)', views_text)
        if views_match:
            item['views'] = views_match.group(1)
        yield item
北邮scrapy框架:

观察发现北邮就业信息网的页面采用ajax动态加载方式,直接请求响应获取的静态页面不包含就业贴的href数据,并且不同的页面因为通过ajax动态加载,并没有特定的url规律。所以我们首先要完成对不同页面的访问请求模拟,并且通过selenium获取页面的动态加载内容,从而获取每个就业贴的url,今而进行后续的工作。

首先利用开发者工具观察北邮就业信息网在进行页面转换时的网络请求,发现页面请求时的ajax请求:

image-20240106202944571

进一步观察ajax的请求内容和相关细节,发现由pageNo参数控制页面转换请求:

image-20240106203155180

决定采用request模块模仿页面转换请求,并封装为由page_no参数唯一决定的函数,函数返回值为响应页面的完整内容:

def fetch_page(page_no):
    url = "https://job.bupt.edu.cn/f/recruitmentinfo/ajax_frontRecruitinfo?ts=1704097062764"
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'
    }
    data = {
        'pageNo': str(page_no),
        'pageSize': '15',
        'positionType': '1',
        'city': '',
        'title': '',
        'corporationNature': '',
        'corporationinfo.industry': ''
    }
    response = requests.post(url=url, headers=headers, data=data)
    return response

从初始页面开始逐次访问页面,获取页面内就业贴的href,同时使用selenium动态访问页面,从而获取页面动态加载的内容:

class MySpider(scrapy.Spider):
    name = "bupt_school"
    allowed_domains = ["job.bupt.edu.cn"]
    def start_requests(self):
        for i in range(1, 100):
            response = fetch_page(i)
            data = json.loads(response.text)
            for item in data['object']['list']:
                base_url = "https://job.bupt.edu.cn/frontpage/bupt/html/recruitmentinfoList.html?type=1&"
                full_url = urljoin(base_url, item['url'])
                item = BuptSchoolItem()
                yield scrapy.Request(url=full_url, callback=self.parse_post, meta={'item': item})

其中middlewares.py中间文件的修改如下,其余文件的修改这里省略:

    def process_spider_input(self, response, spider):
        self.driver.get(response.url)
        time.sleep(3)
        page_source = self.driver.page_source
        html_response = scrapy.http.HtmlResponse(url=response.url, body=page_source.encode('utf-8'), encoding='utf-8')
        return html_response   
    def process_request(self, request, spider):
        url = request.url
        self.driver.get(url)
        time.sleep(1)  # 等待页面加载
        page_source = self.driver.page_source
        html_response = scrapy.http.HtmlResponse(url=url, body=page_source.encode('utf-8'), encoding='utf-8')
        return html_response

后续处理同前文西电,对帖子内容进行相关信息的提取和处理,此处采用css进行内容筛选:

                item['tittle'] = response.css('.name.getCompany::text').get()
        text = response.css('.midInfo .l_con::text').get()  # 获取文本
        views_match = re.search(r'浏览次数:(\d+)', text)
        time_match = re.search(r'日期:(\d{4}-\d{2}-\d{2})', text)
        employer_text = response.xpath('/html/body/div[1]/div[3]/div/text()').get()
        pattern = r'发布企业:\s*([\S]+)'
        employer_match= re.search(pattern, employer_text)

最后,我们对提取的数据进行进一步的处理和分析,保存为excel文件,作为output.excel,按照浏览量重新进行排序保存,作为output2.py,将两者招聘单位相同的内容进行合并,浏览量也进行合并,作为output3.excel。至此,完成了scrapy框架设计和数据获取,并对数据进行了初步处理和分析:

import json
import openpyxl
def process_json_file(input_file, worksheet):
    data = []  # 存储 JSON 数据的列表
    with open(input_file, 'r', encoding='utf-8') as file:
        for line in file:
            item = json.loads(line)
            data.append(item)
    # 按浏览量排序数据
    sorted_data = sorted(data, key=lambda x: int(x.get('views', 0)), reverse=True)
    for item in sorted_data:
        title = item.get('tittle', '')
        employer = item.get('employer', '')
        views = item.get('views', '')
        date = item.get('time', '')
        worksheet.append([title, employer, views, date])

数据分析

分析数据得到最受北邮学生关注的招聘TOP10:

招聘主题招聘单位浏览量日期
华芯巨数(杭州)微电子有限公司2024校园招聘进行中华芯巨数(杭州)微电子有限公司8002023-12-29
【专心致智求贤贴】人工智能大模型科技公司求技术伙伴北京专心致智科技有限公司6222023-12-29
系统设计中电科东方通信集团有限公司6152023-12-22
国家无线电监测中心检测中心2024年校园招聘公告国家无线电监测中心检测中心5942023-12-19
2024航天三院三十五所校园招聘北京华航无线电测量研究所5772023-12-29
华芯巨数(杭州)微电子有限公司2024校园招聘进行中华芯巨数(杭州)微电子有限公司5732023-12-22
航空工业沈阳兴华航空电器有限责任公司2024届校园招聘沈阳兴华航空电器有限责任公司5612023-12-29
中国移动-中移互联网“金种子计划”招聘简章中移互联网有限公司5412023-12-29
巨鲨医疗2024届秋季校园招聘简章南京巨鲨显示科技有限公司5382023-12-21
北京康特瑞科统计科技有限责任公司2024校园招聘北京康特瑞科统计科技有限责任公司5282023-12-19

最受西电学生关注的招聘TOP10:

招聘主题招聘单位浏览量日期
宁波工程学院2023年人才(教师)招聘公告广州高才信息科技有限公司28382023-11-03
深圳市2024年服务高质量发展专项招录紧缺专业公务员深圳市15892023-12-01
北汽集团2024届校园招聘公告北京汽车集团有限公司13772023-11-27
中核霞浦核电有限公司2024年校园招聘公告中核霞浦核电有限公司13602023-11-16
中国航天科技集团有限公司第八研究院第802研究所2024届招聘简章上海无线电设备研究所12972023-11-09
中国船舶集团第七〇七研究所2024届秋季招聘简章中国船舶集团有限公司第七〇七研究所10602023-11-14
中国联通2024校园招聘正式启动中国联合网络通信集团有限公司10222023-11-08
公安部郑州警察学院(原铁道警察学院)2024年度公开招聘硕士博士研究生铁道警察学院10192023-11-11
西咸新区2024届校园直招公告陕西省西咸新区开发建设管理委员会9632023-12-06
2024届陕西省普通高校硕士、博士研究生空中视频双选会邀请函 9392023-12-14

最受两校关注的招聘主题TOP10:

招聘主题招聘单位浏览量日期
北京中科泛华测控技术有限公司2024校园招聘简章北京中科泛华测控技术有限公司4232024-01-05
北京联通新苗计划2024校园招聘公告中国联合网络通信有限公司北京市分公司2872024-01-05
巨鲨医疗2024届秋季校园招聘简章南京巨鲨显示科技有限公司2242024-01-05
中国银行间市场交易商协会2024年度校园招聘公告中国银行间市场交易商协会2312024-01-05
山东外国语职业技术大学高技能人才招聘公告山东外国语职业技术大学2022024-01-05
公安部警用装备采购中心 2024年度公开招聘公告公安部警用装备采购中心2082024-01-05
电子科技大学长三角研究院(衢州)引才计划电子科技大学长三角研究院(衢州)2002024-01-05
河北农业大学2024年选聘博士公告河北农业大学1852024-01-05
北京城市学院 公共英语教研室专兼职教师招聘启事北京城市学院1812024-01-05
浙江大学杭州国际科创中心招聘浙江大学杭州国际科创中心1802024-01-05

对招聘单位进行大致分类并绘制出饼状图:

image-20240106210120457

image-20240106210412437

image-20240106210710382

通过饼状图可以明显看出,事业单位、央企国企、学校单位等工作机会格外受当代大学生的青睐。这可能是因为这些职位通常提供相对稳定的工作环境、较为优厚的福利待遇以及社会地位保障,符合当前年轻人对职业安全和生活质量的追求。与此同时,这也反映出当前就业市场的一个趋势,即在动荡不定的经济环境下,稳定性成为了许多人选择职业时的重要因素。因此,不仅是大学生,很多求职者都倾向于选择那些能提供长期稳定保障的职位。

此外,对于浏览量伴随时间变化绘制对应折线图,如下:

可以发现,随着学期的结束,招聘信息的浏览量来到了一个峰值。这很可能是由于学生们开始积极地为假期工作或毕业后的就业机会做准备,因此他们会更加频繁地浏览相关的招聘信息。此外,许多公司和机构倾向于在学期末或是学年末发布招聘信息,以吸引即将毕业的学生,这也在一定程度上推高了这一时期的浏览量。同时,招聘高峰期也可能与特定行业的招聘季节性有关,某些行业可能在年底或新年伊始前后集中招聘,进一步影响了浏览量的走势。总之,这一现象反映出学生对未来职业的关注以及就业市场的季节性变化。

总结分析

1.对于爬虫框架的设计,需要对各个组件有详细的了解,才可以更好的使用以及进一步的改造它们以适应更具体复杂的需求。

2.爬虫的设计需要基于页面的具体特性,在面对一些拥有特殊性质的页面,要因事制宜,针对不同的特点针对性的设计爬虫组件。

3.模块化设计的思想,将大的内容分割成小的部分,逐一解决。

4.要学会善于利用程序来解决大量、固定、重复的事情,从而提升生产效率,这也是学习编程的一个很重要的目的。

评论(0)

发布评论