欢迎访问我的个人网站http://liubofeng.com
网页分析
博主在本博客中爬取的是数据分析岗位。
进入网站首页https://www.shixiseng.com/搜索数据分析,F12审查元素,可以发现岗位的薪资以及其他用数字表示的信息都被加密了,如下图所示:
这也就意味着如果不破解字体加密,那么爬取到的薪资及其他数字数据将全部是上图中的乱码。
ctrl+u进入到网页源码,可以发现数据全是写在dom节点中的,那么只要破解字体加密再用xpath解析dom节点就可以爬取数据了。
F12审查元素,查看数字采用的哪一种字体:
从上图可以看到采用的是一种自定义字体:myFont
ctrl+u进入网页源码,ctrl+f在网页源码中搜索该字体: myFont,搜索结果如下图:
从上图可以看到该字体文件的相对路径,将该路径与实习僧的域名拼接即可得到完整的字体路径:www.shixiseng.com/interns/iconfonts/file?rand=0.12285263573042116
在浏览器中输入该路径就会下载一个名为file的文件,注意该文件是没有后缀名的,如下图:
将该文件重命名为file.ttf,然后将file.ttf文件移动到与你写的python文件的同一目录下,如下图所示,file.ttf文件与shixiseng.py文件都在实习僧_spider文件夹下,在同一目录下是为了方便在程序中使用file.ttf文件。
在网页源码中,可以看到薪资被替换成了这样一串代码:
-/天,与原网页对比就可以知道这串代码代表的是120-180/天。
现在要知道是怎么解码成120的。
#将字体文件解析成xml文件
from fontTools.ttLib import TTFont
font = TTFont("file.ttf")
font.saveXML("font.xml")
在xml文件中搜索不到,,,但是可以搜到xf0c7,xe3c6,xe3f5,下图是包含xf0c7的代码,code是键,name是值。
将name的值的uni后的字符31进行unicode解码,也就是对\u0031转中文得到1。
那么数字1的转换逻辑为=>0xf0c7=>uni31=>\u0031=>1
代码
接下来直接上完整爬虫代码。
import requests
import xlwt
import urllib.parse
from lxml import etree
import re
from fontTools.ttLib import TTFont
font = TTFont("file.ttf")
font.saveXML("font.xml")
def get_dict():
#打开并读取font.xml
with open('font.xml') as f:
xml = f.read()
#正则表达式提取code和name
keys = re.findall('<map code="(0x.*?)" name="uni.*?"/>', xml)
values = re.findall('<map code="0x.*?" name="uni(.*?)"/>', xml)
word_dict={}
# 将name解码成中文并作为值写入字典word_dict,该字典的键为keys
for i in range(len(values)):
if len(values[i]) < 4:
values[i] = ('\\u00' + values[i]).encode('utf-8').decode('unicode_escape')
else:
values[i] = ('\\u' + values[i]).encode('utf-8').decode('unicode_escape')
word_dict[keys[i]]=values[i]
print(word_dict)
return word_dict
dict=get_dict()
#输入要爬取的岗位名称并转urlencode编码
job=input('请输入你要在实习僧爬取的实习岗位名称:')
job_urlencode=urllib.parse.quote(job)
def spider_sxs():
#创建execl并设置列名
workbook = xlwt.Workbook(encoding='utf-8')
sheet1 = workbook.add_sheet('{}'.format(job))
sheet1.write(0,0,'职位名称')
sheet1.write(0,1,'工资')
sheet1.write(0,2,'城市')
sheet1.write(0,3,'出勤要求')
sheet1.write(0,4,'实习周期')
sheet1.write(0,5,'职位福利')
sheet1.write(0,6,'公司名称')
sheet1.write(0,7,'所属行业')
sheet1.write(0,8,'公司规模')
sheet1.write(0,9,'投递链接')
sheet1.write(0,10,'公司链接')
# 设置excel列宽度
sheet1.col(0).width = 256 * 30
sheet1.col(1).width = 256 * 20
sheet1.col(2).width = 256 * 10
sheet1.col(3).width = 256 * 15
sheet1.col(4).width = 256 * 15
sheet1.col(5).width = 256 * 60
sheet1.col(6).width = 256 * 20
sheet1.col(7).width = 256 * 20
sheet1.col(8).width = 256 * 15
sheet1.col(9).width = 256 * 30
sheet1.col(10).width = 256 * 30
sheet1_row=0
# 解析网页源代码
for i in range(1,int(input('请输入要爬取{}岗位的页数:'.format(job)))+1):
url='https://www.shixiseng.com/interns?page={}&type=intern&keyword={}&area=&months=&days=°ree=&official=&enterprise=&salary=-0&publishTime=&sortType=&city=%E5%85%A8%E5%9B%BD&internExtend='.format(i,job_urlencode)
print('第{}页的链接是:{}'.format(i,url))
response=requests.get(url)
response_text=response.text.replace('&#','0') #将源码中=>0xefed
for key in dict:
response_text=response_text.replace(key,dict[key]) #0xefed格式=>对应的字典的值
html_sxs=etree.HTML(response_text)
all_div=html_sxs.xpath('//*[@id="__layout"]/div/div[2]/div[2]/div[1]/div[1]/div[1]//div[@class="intern-wrap intern-item"]')
# 循环语句获取数据并存入excel
for item in all_div:
try:
# 获取数据
job_name = item.xpath('.//a[@class="title ellipsis font"]/text()')[0] #职位名称
wages = item.xpath('.//span[@class="day font"]/text()')[0] #工资
city = item.xpath('.//span[@class="city ellipsis"]/text()')[0] #城市
week_time = item.xpath('.//span[@class="font"]/text()')[0] #出勤要求
work_time = item.xpath('.//span[@class="font"]/text()')[1] #实习周期
job_welfare = item.xpath('.//span[@class="company-label"]/text()')[0] #职位福利
company_name = item.xpath('.//a[@class="title ellipsis"]/text()')[0] #公司名称
company_type = item.xpath('.//span[@class="ellipsis"]/text()')[0] #所属行业
company_size = item.xpath('.//span[@class="font"]/text()')[2] #公司规模
job_href = item.xpath('.//a[@class="title ellipsis font"]/@href')[0] #投递链接
company_href = item.xpath('.//a[@class="title ellipsis"]/@href')[0] #公司链接
# 向execl写入数据
sheet1_row=sheet1_row+1
sheet1.write(sheet1_row,0,job_name)
sheet1.write(sheet1_row,1,wages)
sheet1.write(sheet1_row,2,city)
sheet1.write(sheet1_row,3,week_time)
sheet1.write(sheet1_row,4,work_time)
sheet1.write(sheet1_row,5,job_welfare)
sheet1.write(sheet1_row,6,company_name)
sheet1.write(sheet1_row,7,company_type)
sheet1.write(sheet1_row,8,company_size)
sheet1.write(sheet1_row,9,job_href)
sheet1.write(sheet1_row,10,company_href)
except:
''
workbook.save('实习僧{}岗位.xls'.format(job))
print('爬取成功')
print('------------------------------------------------------')
spider_sxs()
结果
爬取结果部分截图如下: