项目开发过程中的知识点收获
用csv文件存储数据时,同步自定义设置表头的代码实现
要点:在写入csv文件时,设置参数header。写入顺序即为自身设置的顺序
form_header = ['职位名称','职级','职位族']
数据 = pd.DataFrame({'职位名称':job_name_list,'职级':job_level_list,'职位族':job_family_list})
数据.to_csv('d:/职位信息.csv',mode='a',header=form_header,encoding='ANSI')
DataFrame中的字典结构数据,键名后面的值的数据类型必须是列表的类型。
数据 = pd.DataFrame({'职位名称':job_name_list,'职级':job_level_list,'职位
函数调用报错-name 'children_page' is not define
解决方式:把自己定义写好的函数放在主函数的最前面。因为程序编译器的解析,是从上到下进行编译执行的。上述错误即是因为函数没有定义的问题。
子页面链接点击爬取问题
browser = webdriver.Chrome()
browser=job_name.click()
print(browser)
在子函数中,尝试新建浏览器对象来进行详情页面的关键信息抓取,但点击列表页超链接后,并未有接收到任何返回值。
子页面链接点击爬取后的返回值问题
现象:返回值必须含有浏览器对象,否则在下一次运行函数,会出现如下报错;
StaleElementReferenceException: stale element reference: element is not attached to the page document
(Session info: chrome=97.0.4692.71)
def children_page(job_name):
job_name.click()
页面 = 浏览器对象.window_handles
#print(页面)
#浏览器对象切换到所有打开
浏览器对象.switch_to.window(页面[-1])
time.sleep(3)
job_name=浏览器对象.find_element_by_xpath('//*[@id="showTab"]/div[3]/div[1]/h1/label[1]')
work_place=浏览器对象.find_element_by_xpath('//*[@id="addressDiv"]/label[1]')
update=浏览器对象.find_element_by_xpath('//*[@id="showTab"]/div[3]/div[1]/ul/li[1]/label')
department=浏览器对象.find_element_by_xpath('//*[@id="jobDeptLabel"]')
job_family=浏览器对象.find_element_by_xpath('//*[@id="showTab"]/div[3]/div[3]/ul/li[5]/label')
job_level=浏览器对象.find_element_by_xpath('//*[@id="jobLevelTitle"]')
job_duty=浏览器对象.find_element_by_xpath('//*[@id="mainBusiness"]')
job_request=浏览器对象.find_element_by_xpath('//*[@id="demand"]')
print(job_name.text)
print(work_place.text)
print(update.text)
print(department.text)
print(job_family.text)
print(job_level.text)
print(job_duty.text)
print(job_request.text)
浏览器对象.close()
time.sleep(2)
#将浏览器对象切回到原有列表页这一点很重要
浏览器对象.switch_to.window(页面[0])
return 浏览器对象
函数返回值如果有多个,其实返回的是元组。Python的函数返回多值其实就是返回一个tuple,但写起来更方便。
函数返回多个值,只取部分值
一个常见的惯例是使用“_“作为要忽略的元组元素的变量名。例如:
def f():
return 1, 2, 3
_, _, x = f()
异常问题:下拉加载多项之后,点击详细页的加载方式失效
具体报错代码如下:
ElementClickInterceptedException: element click intercepted: Element ... is not clickable at point (168, 10). Other element would receive the click: ...
(Session info: chrome=97.0.4692.71)
完整成功代码如下
import requests
import json
import pandas as pd
import time
import xlwt
from lxml import etree
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver import ActionChains # 动作链
#定义抓取详情页的函数-直接点击子页面爬取的方式
def children_page(button):
#利用动作链将浏览器页面定位到链接点击处
ActionChains(浏览器对象).move_to_element(button).perform()
button.click()
页面 = 浏览器对象.window_handles
#浏览器对象切换到列表页打开
浏览器对象.switch_to.window(页面[-1])
time.sleep(3)
job_name=浏览器对象.find_element_by_xpath('//*[@id="showTab"]/div[3]/div[1]/h1/label[1]')
work_place=浏览器对象.find_element_by_xpath('//*[@id="addressDiv"]/label[1]')
update=浏览器对象.find_element_by_xpath('//*[@id="showTab"]/div[3]/div[1]/ul/li[1]/label')
department=浏览器对象.find_element_by_xpath('//*[@id="jobDeptLabel"]')
job_family=浏览器对象.find_element_by_xpath('//*[@id="showTab"]/div[3]/div[3]/ul/li[5]/label')
job_level=浏览器对象.find_element_by_xpath('//*[@id="jobLevelTitle"]')
job_duty=浏览器对象.find_element_by_xpath('//*[@id="mainBusiness"]')
job_request=浏览器对象.find_element_by_xpath('//*[@id="demand"]')
# print(job_name.text)
dir_data={
'goal_job_name':job_name.text,
'goal_work_place':work_place.text,
'goal_update':update.text,
'goal_department':department.text,
'goal_job_family':job_family.text,
'goal_job_level':job_level.text,
'goal_job_duty':job_duty.text,
'goal_job_request':job_request.text
}
浏览器对象.close()
time.sleep(2)
#将浏览器对象切回到原有列表页这一点很重要
浏览器对象.switch_to.window(页面[0])
return 浏览器对象,dir_data
#主程序
网址 = 'http://XXXXXhtml'
UA伪装 = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36'}
proxies={
'http':'http://XXXX@XXXX',
'https':'XXXX@pXXXX'
}
#无头模式配置
'''
chrome_options=webdriver.ChromeOptions()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
浏览器对象 = webdriver.Chrome(chrome_options=chrome_options)
'''
# 获取[浏览器]的实例化对象
浏览器对象 = webdriver.Chrome()
# 使用浏览器打开网址
浏览器对象.get(网址)
#因为网络存在延迟,所以需要延缓几秒打开网页,否则可能存在元素未完全加载的情况
time.sleep(5)
浏览器对象.find_element_by_id('poolSelectCheckTips').click()
浏览器对象.find_element_by_id('btnconfirm').click()
time.sleep(3)
#job_name = 浏览器对象.find_element_by_xpath('//div[@class="centent_l fl"]//h3/a/@title')
#实测发现先点击职位族,再点击职级抓取的数据相对会更准确一些。两者顺序调换后,抓取的数据中前面几个会有技术族的信息。
#筛选条件点击-职位族
浏览器对象.find_element_by_xpath('//dd[@id="positionList"]//a[@data="J03"]').click()
time.sleep(5)
#筛选条件点击-职级
浏览器对象.find_element_by_xpath('//dd[@id="joblevelList"]/a[@data="13,14"]').click()
#点击之后暂缓3秒,等待数据加载
time.sleep(5)
#print(type(job_name))
job_name_list=[]
job_level_list=[]
job_family_list=[]
dir_data_list=[]
goal_job_name_list=[]
goal_work_place_list=[]
goal_update_list=[]
goal_department_list=[]
goal_job_family_list=[]
goal_job_level_list=[]
goal_job_duty_list=[]
goal_job_request_list=[]
#列表页的元素获取
#job_level=浏览器对象.find_element_by_xpath('//div[@class="centent_l fl"]/p')
#job_family=浏览器对象.find_element_by_xpath('//div[@class="centent_l fl"]/div')
#job_link1=job_name.get_attribute('href')
#job_link='http://w3.huawei.com'+job_link1
#将页面滚动条拉到页面的底部
i=1
while i!=80:
js="var q=document.documentElement.scrollTop=100000"
浏览器对象.execute_script(js)
time.sleep(2)
i=i+1
print(i)
#初始未有翻页的超链接抓取
#job_name = 浏览器对象.find_elements_by_xpath('//div[@class="centent_l fl"]//h3/a')
#开始有翻页后的链接抓取
button = 浏览器对象.find_elements_by_xpath('//div[@class="centent_l fl"]//h3/a')
#print(button)
#print(job_name[0],job_name[1])
for element in button:
_,x=children_page(element)
print(x)
#print(x.values())
goal_job_name_list.append(x['goal_job_name'])
goal_work_place_list.append(x['goal_work_place'])
goal_update_list.append(x['goal_update'])
goal_department_list.append(x['goal_department'])
goal_job_family_list.append(x['goal_job_family'])
goal_job_level_list.append(x['goal_job_level'])
goal_job_duty_list.append(x['goal_job_duty'])
goal_job_request_list.append(x['goal_job_request'])
#将列表字典中的数据进行提取,准备文件储存
print(goal_job_name_list)
print(goal_work_place_list)
数据 = pd.DataFrame({'职位名称':goal_job_name_list,'工作地':goal_work_place_list,'发布时间':goal_update_list,'岗位部门':goal_department_list,'职位族':goal_job_family_list,'职级':goal_job_level_list,'岗位职责':goal_job_duty_list,'任职要求':goal_job_request_list,})
数据.to_excel('d:/job_information.xlsx')
#数据.to_csv('d:/职位信息.csv',mode='a',header=form_header,encoding='ANSI')
附录-网页加载过程中的一些逻辑分析(已无太大意义)
项目开发-inner
-
目标网站及基本特征数据
主页网址:http://w3.huawei.com/ihrm/hometalent_index.html
刚进入主页后的输入框勾选:
勾选输入框之后的确认键:确定
职位信息是在
//*[@id="postCentent"]/div[1]/div[1]/h3/a
-
网站特点及加载逻辑分析
刚刚进入网站时,会发生链接的重定向跳转。弹出一个框框让勾选,比较讨厌
网页是属于Ajax异步加载的,通过下拉加载更多,会发送Ajax请求。
点击职级时,出现的异步加载链接:http://w3.huawei.com/ihrm/services/hometalent/portal/newPortal/findAllJobForPortal/10/1?jobLevel=13%2C14&orderBy=LAST_UPDATE_DATE_DESC&someondeCount=17
点击职位族时,出现的异步加载链接:http://w3.huawei.com/ihrm/services/hometalent/portal/newPortal/findAllJobForPortal/10/1?jobFamily=J19&orderBy=LAST_UPDATE_DATE_DESC&someondeCount=19
【规律发现】:在这个Ajax请求里有发现,职级为obLevel=13%2C14这种,职位族为jobFamily
-
尝试获取日志
-
2022/1/10-利用XPath获取数据当前存在问题
- 具体描述:XPath的具体应用,如何锁定具体的元素路径。
-
【已解决】-直接爬取在职级这一异步加载链接时,出现如下错误提示:
{"httpCode":403,"faultUid":"WebContainer : dggmwc5app355-Anonymous-9-9-48-30-508-2109","code":"huawei.jalor5.security.00010002","message":"您当前未登录。","entity":null,"stackTrace":""}
解决方式:尝试更换网址链接,从主页进入。
-