数据分析这个职位有前途吗?--数据采集(一)
首先我们对数据进行抽样,目前招聘网站比较多,选取其中一个网站(前程无忧),并只是分析一个城市(广州)进行分析,通过scrapy爬虫的框架对招聘的职位进行数据抓取,并导出csv文件。
1. 分析招聘网站的页面数据结构
1.1 职位列表分析
通过网站输入数据分析职位并选择广州地区,跳转到一个职位列表,该列表只有5列数据显示并且是通过分页显示,5列数据不能满足后面分析维度的需要
image.png
1.2 职位详情分析
职位详情的信息比较多,包括了对应聘者的学历,工作经验,能力要求,招聘公司的类型,人数,招聘人数,薪资要求等多个维度的数据。
image.png
1.3 数据获取的思路
(1)获取职位招聘信息的列表的查看详情的url地址。
(2) 通过url地址访问详情页面,获取详情页面的信息。
2 爬虫程序的代码实现
2.1 项目创建
在cmd控制台执行“scrapy startproject job_spider” 生成如下图的结构的代码文件,其中itemload.py,main.py文件,data目录是后面添加的,后面会讲到这几个文件,在eclipse新建一个python的项目,把相应的文件拷贝进来。
新建main.py文件,是为了能够在eclipse里面调试项目,并且在文件里面添加下面的代码,该代码就是整个爬虫项目的入口,运行项目并把结构导出到csv文件,其中%(name)s 表示爬虫的名称的占位符,%(time)s表示导出文件的时间
if __name__ == '__main__':
cmdline.execute(argv=['scrapy','crawl','51job','-o','data/export_%(name)s_%(time)s.csv'])
2.2 招聘列表的数据读取实现
1 class JobSpider(scrapy.Spider):
2 name = "51job"
3 start_urls = [
4 "https://search.51job.com/list/030200,000000,0000,00,9,99,%25E6%2595%25B0%25E6%258D%25AE%25E5%2588%2586%25E6%259E%2590,2,1.html?lang=c&stype=&postchannel=0000&workyear=99&cotype=99°reefrom=99&jobterm=99&companysize=99&providesalary=99&lonlat=0%2C0&radius=-1&ord_field=0&confirmdate=9&fromType=&dibiaoid=0&address=&line=&specialarea=00&from=&welfare="
5 ]
6 def parse(self, response):
7 list=response.xpath('//*[@id="resultList"]/div')
8 for info in list:
9 name=info.xpath('p/span/a/text()').extract_first()
10 url=info.xpath('p/span/a/@href').extract_first()
11 if not name is None:
12 yield scrapy.Request(url,callback=self.parse_detail)
13
14 next_url=response.css('#resultList > div.dw_page > div > div > div > ul > li:last-child>a::attr(href)').extract_first();
15 if next_url:
16 yield scrapy.Request(next_url,callback=self.parse)
第3行:数据分析,广州地区的职位列表的url,这个地址作为爬虫的开始地址
第6行:该方法是爬虫框架解析完成页面后,进行调用的解析方法
第7行:获取职位信息的列表区域的对象
第10行:循环职位列表的数据,获取对应的详情地址的url
第12行:调用详情地址的解析方法
第14行:获取职位列表的下一页的链接元素
第16行:继续解析职位列表的下一页的数据
2.3 招聘列表的详情页面读取实现
1def parse_detail(self, response):
2 job_title=response.xpath('/html/body/div[3]/div[2]/div[2]/div/div[1]/h1/text()').extract_first()
3 work_info=response.xpath('/html/body/div[3]/div[2]/div[2]/div/div[1]/p[2]/text()').extract()
4 salary=response.xpath('/html/body/div[3]/div[2]/div[2]/div/div[1]/strong/text()').extract_first()
5 company_name=response.xpath('/html/body/div[3]/div[2]/div[4]/div[1]/div[1]/a/p/text()').extract_first()
6 company_type=response.xpath('/html/body/div[3]/div[2]/div[4]/div[1]/div[2]/p[1]/text()').extract_first()
7 company_num=response.xpath('/html/body/div[3]/div[2]/div[4]/div[1]/div[2]/p[2]/text()').extract_first()
8 business=response.xpath('/html/body/div[3]/div[2]/div[4]/div[1]/div[2]/p[3]/text()').extract_first()
9 job_desc=response.xpath('/html/body/div[3]/div[2]/div[3]/div[1]/div//text()').extract()
10 l=JobItemLoad(JobItem())
11 if len(work_info)>=5:
12 l.add_value('work_place', work_info[0])
13 l.add_value('work_experience', work_info[1])
14 l.add_value('education', work_info[2])
15 l.add_value('headcount', work_info[3])
16 l.add_value('publish_date', work_info[4])
17 elif len(work_info)==4:
18 l.add_value('work_place', work_info[0])
19 l.add_value('work_experience', work_info[1])
20 l.add_value('headcount', work_info[2])
21 l.add_value('publish_date', work_info[3])
22 l.add_value('job_title', job_title)
23 l.add_value('salary', salary)
24 l.add_value('company_name', company_name)
25 l.add_value('company_type', company_type)
26 l.add_value('company_num', company_num)
27 l.add_value('business', business)
28 l.add_value('job_desc', "".join(job_desc))
29 l.add_value("url", response.url)
30 yield l.load_item()
第2-9行:获取页面解析的数据
第10行:生成ItemLoader对象
第11-29行:进行数据赋值
第30行:返回详情的数据
2.4 爬取的数据处理
文件items.py是对爬取的数据进行处理的文件,由于爬取下列的文件有一些特殊的字符,还有换行,空格等问题,通过这个文件对数据进行一些处理
1def normalize_space(value):
2 move = dict.fromkeys((ord(c) for c in u"\xa0\n\t\r"))
3 output = value.translate(move)
4 return output
5class JobItem(scrapy.Item):
6 job_title = scrapy.Field(input_processor=MapCompose(normalize_space))#职位名称
7 work_place=scrapy.Field(input_processor=MapCompose(normalize_space))#工作地点
第2行:定义要移除的字符
第6行:定义该字段的处理的方法,用MapCompost可以定义多个处理方法
3 踩过的坑
3.1 导出文件乱码
需要在settings.py文件添加如下配置
FEED_EXPORT_ENCODING = "gb18030"
3.2 字段处理没有生效
需要在itemload.py文件添加如下代码
default_output_processor = TakeFirst()
关注公众号,回复“51job”获取项目代码