# 数据挖掘期中项目 **Repository Path**: gaogaolo/data-mining-interim-project ## Basic Information - **Project Name**: 数据挖掘期中项目 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2021-05-19 - **Last Updated**: 2022-09-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 数据挖掘期中项目 * 作者:高智浩 ## 爬取网页51job ### 首先进行模块调用并对网站进行解析 ``` from requests_html import HTMLSession import requests_html import urllib.parse import pandas as pd ``` ``` url = 'https://search.51job.com/list/030200,000000,0000,00,9,99,+,2,1.html?lang=c&postchannel=0000&workyear=01&cotype=99°reefrom=99&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare=' session = HTMLSession() res = session.get(url) res ``` ### 参数获取清洗以及参数构建 * 由于51job是动态加载网页,所以需要先爬取js信息获取参数数据 ``` footer = "http:"+res.html.xpath('//script')[-3].html.split("\"")[3] import requests resp = requests.get(footer) resp.content.decode("gbk","ignore") 参数 = resp.content.decode("gbk","ignore") ``` * 由于获取到的js数据类型复杂且繁琐,所以需要对获取到的参数信息进行单独拆分清洗处理来获取需要的分类参数信息(以公司分类为例) ``` 公司性质 = 参数.split("search_cottype=")[1].split(",window.d_search_workyear")[0] 公司性质1 = 公司性质.replace('k:"','').replace('}','').replace("{","").replace('[','').replace(']','').replace('"','') 公司性质2 = 公司性质1.replace(',v:','=') 公司性质分类 = 公司性质2.split(',') 公司性质分类 = list(公司性质分类) 公司性质_str = ["请选择","国企","外资(欧美)","外资(非欧美)","上市公司","合资","民营公司","外企代表处","政府机关","事业单位","非营利组织","创业公司"] 公司性质_dict = {i:公司性质分类[k].split('=')[0] for k,i in enumerate(公司性质_str)} 公司性质_参数构建 = {公司性质_str[i]:公司性质分类[i].split('=')[0] for i in range(len(公司性质分类))} ``` * 然后便可以得出 公司性质的参数构建(别的分类参数同理) ``` {'请选择': '99', '国企': '04', '外资(欧美)': '01', '外资(非欧美)': '02', '上市公司': '10', '合资': '03', '民营公司': '05', '外企代表处': '06', '政府机关': '07', '事业单位': '08', '非营利组织': '09', '创业公司': '11'} ``` ### 构建参数模板 * 在对分类信息进行参数构建后便可以开始构建参数模板 ``` 参数模版 = urllib.parse.urlparse(url) 参数模版_list = pd.Series(参数模版).tolist() print("参数模版_list=",参数模版_list,'\n') 参数模版_dict = {i.split("=")[0]:i.split("=")[1] for i in 参数模版.query.split("&")} 参数模版_dict ``` ``` def url_参数模板生成(cotype,degreefrom,workyear): cotype = 公司性质_参数构建[cotype] degreefrom = 学历要求_参数构建[degreefrom] workyear = 工作年限_参数构建[workyear] 参数模版_dict["cotype"] = cotype 参数模版_dict["degreefrom"] = degreefrom 参数模版_dict["workyear"] = workyear query_事业单位 = "&".join([k+"="+v for k,v in 参数模版_dict.items()]) 参数模版_list[4] = query_事业单位 url_参数 = urllib.parse.urlunparse(参数模版_list) return (url_参数) ``` * 在把参数模板构建成功之后就可以输入参数信息进行自动生成网站(我所构建的是公司性质,学历要求,工作年限以及搜索关键词) ``` 关键词 = urllib.parse.quote("产品经理") 参数模板url = url_参数模板生成('请选择','本科',"在校生/应届生") 参数模板url_2 = 参数模板url.replace('+',关键词) 参数模板url_2 ``` * 输入好以上要生成的信息后便可获得自动生成的网站链接 ` 'https://search.51job.com/list/030200,000000,0000,00,9,99,%E4%BA%A7%E5%93%81%E7%BB%8F%E7%90%86,2,1.html?lang=c&postchannel=0000&workyear=01&cotype=99°reefrom=04&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare=' ` ### 抓取页面内容以及工作详细页链接并进行清洗 * 在获得目标生成的参数模板链接后,便可对页面信息进行爬取 * 由于网站是动态储存数据,所以要从js中获取页面数据内容,而不能用xpath ``` session = HTMLSession() r = session.get(参数模板url_2) g = r.html __SEARCH_RESULT__ = g.xpath('//script')[-4].html.split("__SEARCH_RESULT__ = ")[1].split("")[0] results = eval(__SEARCH_RESULT__) results ``` * 获取到js数据后筛选出所需的数据类型并建立表格 ``` 招聘信息_df = pd.DataFrame(results['engine_search_result']) 招聘信息_df ``` * 再从数据表格中筛选出工作详细页的链接并对其进行清洗(清洗详细页当中的反斜杠,否则会由于链接格式不正确导致后面数据无法爬取) ``` 招聘信息_df["job_href"] url_all = list(招聘信息_df['job_href']) SYMBOLS = '\\' url_all_2 = [] for i in url_all: temp = "" for j in i: if j not in SYMBOLS: temp += j url_all_2.append(temp) url_all_2 ``` ### 详细页数据爬取 * 在对详细页链接进行清洗后便可以对详细页所需信息进行爬取 ``` 职称 = [] 公司信息 = [] 职位信息 = [] 薪酬 = [] 工作信息 = [] for i in url_all_2: session = HTMLSession() c = session.get(i) 职称.append(c.html.xpath('//div[@class="tCompanyPage"]/div[@class="tCompany_center clearfix"]/div/div/div/h1/@title')) 公司信息.append(c.html.xpath('//div[@class="tCompanyPage"]/div[@class="tCompany_center clearfix"]/div[@class="tHeader tHjob"]/div[@class="in"]/div[@class="cn"]/p[@class="cname"]/a[@class="catn"]/@title')) 职位信息.append(c.html.xpath('//div[@class="tCompanyPage"]/div[@class="tCompany_center clearfix"]/div[@class="tCompany_main"]/div[@class="tBorderTop_box"]/div[@class="bmsg job_msg inbox"]/p/text()')) 薪酬.append(c.html.xpath('//div[@class="tCompanyPage"]/div[@class="tCompany_center clearfix"]/div[@class="tHeader tHjob"]/div[@class="in"]/div[@class="cn"]/strong/text()')) 工作信息.append(str(c.html.xpath('//div[@class="tCompanyPage"]/div[@class="tCompany_center clearfix"]/div[@class="tHeader tHjob"]/div[@class="in"]/div[@class="cn"]/p[@class="msg ltype"]/@title')).replace('\\xa0','')) pd.DataFrame({ "职称":职称, "工作信息":工作信息, "公司信息":公司信息, "薪酬":薪酬, "职位信息":职位信息, }) ``` ### 翻页爬取51job * 在成功抓取单页内容以及详细页后,便尝试进行翻页爬取 * 首先利用format函数找出翻页链接(以前三页为例) #### 获取翻页链接 ``` fanye = [] for h in range(1,4): fanye.append("https://search.51job.com/list/030200,000000,0000,00,9,99,%E4%BA%A7%E5%93%81%E7%BB%8F%E7%90%86,2,{num}.html?lang=c&postchannel=0000&workyear=01&cotype=99°reefrom=04&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare=".format(num = h)) fanye ``` * 获得前三页链接 ``` ['https://search.51job.com/list/030200,000000,0000,00,9,99,%E4%BA%A7%E5%93%81%E7%BB%8F%E7%90%86,2,1.html?lang=c&postchannel=0000&workyear=01&cotype=99°reefrom=04&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare=', 'https://search.51job.com/list/030200,000000,0000,00,9,99,%E4%BA%A7%E5%93%81%E7%BB%8F%E7%90%86,2,2.html?lang=c&postchannel=0000&workyear=01&cotype=99°reefrom=04&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare=', 'https://search.51job.com/list/030200,000000,0000,00,9,99,%E4%BA%A7%E5%93%81%E7%BB%8F%E7%90%86,2,3.html?lang=c&postchannel=0000&workyear=01&cotype=99°reefrom=04&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare='] ``` * 再对这三页内容进行解析 ``` fanye_all=[] for i in fanye: session = HTMLSession() fanye_all.append(session.get(i)) fanye_all ``` #### 整合翻页内容 * 解析完成后对翻页内容进行集体爬取并且整合在同一列表 ** 爬取三页所有数据 ``` results = [] for fan in fanye_all: __SEARCH_RESULT__ = fan.html.xpath('//script')[-4].html.split("__SEARCH_RESULT__ = ")[1].split("")[0] results.append(eval(__SEARCH_RESULT__)) results ``` ** 对三页数据进行整合 ``` results_2 = [] for page in range(3): results_2.append(results[page]) results_2 ``` * 筛选出翻页爬取后总共150条的详细页链接 ``` results_3 = [] for v in range(3): for n in range(50): results_3.append(results_2[v]['engine_search_result'][n]['job_href']) results_3 ``` * 对翻页爬取的详细页信息进行清洗整合(去除反斜杠使得网站格式正确可以被爬取) ``` fanye_all = list(results_3) SYMBOLS = '\\' fanye_all_2 = [] for i in fanye_all: temp = "" for j in i: if j not in SYMBOLS: temp += j fanye_all_2.append(temp) fanye_all_2 ``` #### 爬取翻页整合后所有详细页内容 ``` 职称 = [] 公司信息 = [] 职位信息 = [] 薪酬 = [] 工作信息 = [] for i in fanye_all_2: session = HTMLSession() c = session.get(i) 职称.append(c.html.xpath('//div[@class="tCompanyPage"]/div[@class="tCompany_center clearfix"]/div/div/div/h1/@title')) 公司信息.append(c.html.xpath('//div[@class="tCompanyPage"]/div[@class="tCompany_center clearfix"]/div[@class="tHeader tHjob"]/div[@class="in"]/div[@class="cn"]/p[@class="cname"]/a[@class="catn"]/@title')) 职位信息.append(c.html.xpath('//div[@class="tCompanyPage"]/div[@class="tCompany_center clearfix"]/div[@class="tCompany_main"]/div[@class="tBorderTop_box"]/div[@class="bmsg job_msg inbox"]/p/text()')) 薪酬.append(c.html.xpath('//div[@class="tCompanyPage"]/div[@class="tCompany_center clearfix"]/div[@class="tHeader tHjob"]/div[@class="in"]/div[@class="cn"]/strong/text()')) 工作信息.append(str(c.html.xpath('//div[@class="tCompanyPage"]/div[@class="tCompany_center clearfix"]/div[@class="tHeader tHjob"]/div[@class="in"]/div[@class="cn"]/p[@class="msg ltype"]/@title')).replace('\\xa0','')) 翻页详细页总合 = pd.DataFrame({ "职称":职称, "工作信息":工作信息, "公司信息":公司信息, "薪酬":薪酬, "职位信息":职位信息, }) 翻页详细页总合 ```