参考博客:http://www.cnblogs.com/eastonliu/p/9925652.html

实习僧招聘的网站采用了字体反爬,在页面上显示正常,查看源码关键信息乱码,如下图所示:

查看网页源码也是看不到关键信息:

查了一下是css3支持自定义字体,实习僧技术人员把一些字体换成了自定义的字体,浏览器上可以显示,后台就看不到了。

1.首先找到这些字体是在哪定义的。

右键查看网页源码,查找font-face,就会看到字体信息(加密的数据太多):

可以看到这些字体源是用了base64加密,用base64库进行解密,把解密后的字体文件保存到shixi.ttf中,下载一个字体软件FontCreator。链接:https://pan.baidu.com/s/1BPRhWYvOs6KFrgNQ4h7m_g 提取码:1fa4

1 def parse_ttf():
2 font_face = " 源码上的font-face"
3 b = base64.b64decode(font_face)
4 with open('shixi.ttf', 'wb') as f:
5 f.write(b)

用软件打开这个字体文件,可以右键-Captions-Codepoints选择排序方式:

可以看到这是网页替换的字体,例如:e588---1,ebbc---5.

2.接下来就是找到这些字体和源码中相应位置字符的对应关系。

ttf文件直接打不开,可以转换成xml文件打开或者用from fontTools.ttLib import TTFont 这个库打开。

1 def font_dict():
2 font = TTFont('shixi.ttf')
3 font.saveXML('shixi.xml')

打开shixi.xml,找到cmap,这里保存了编码和字体的对应关系。

接下来就是获取这种对应关系,code所示的就是网页上的源码形式,但是用getBestCmap()函数获取后又变成十进制的数了,所以需要用hex()函数将10进制整数转换成16进制,以字符串形式表示成原来的行是。

这里有一个坑,第一行的map没有用,如果不删除接下来没办法解析。

 1 def font_dict():
2 font = TTFont('shixi.ttf')
3 font.saveXML('shixi.xml')
4 ccmap = font['cmap'].getBestCmap()
5 print("ccmap:\n",ccmap)
6 newmap = {}
7 for key,value in ccmap.items():
8 # value = int(re.search(r'(\d+)', ccmap[key]).group(1)) - 1
9 #转换成十六进制
10 key = hex(key)
11 value = value.replace('uni','')
12 a = 'u'+'0' * (4-len(value))+value
13 newmap[key] = a
14 print("newmap:\n",newmap)
15 #删除第一个没用的元素
16 newmap.pop('0x78')
17 #加上前缀u变成unicode....
18 for i,j in newmap.items():
19 newmap[i] = eval("u" + "\'\\" + j + "\'")
20 print("newmap:\n",newmap)
21
22 new_dict = {}
23 #根据网页上显示的字符样式改变键值对的显示
24 for key, value in newmap.items():
25 key_ = key.replace('0x', '&#x')
26 new_dict[key_] = value
27
28 return new_dict

这样就得到了网页代码和实际字符额对应关系,如下:

'0xe06b': '天', '0xe0ce': '个', '0xe0d2': 'p', '0xe0d4': 'K', '0xe109': 's'

3.替换网页上的编码,提取正确的信息。

下面是全部源码:

  1 #coding=utf-8
2 #milo22233060@gmail.com
3 #2018/11/8 17:01
4 import requests
5 import re
6 from lxml import etree
7 import base64
8 import json
9 import pymysql
10 import time
11 from fontTools.ttLib import TTFont
12 def parse_ttf():
13 font_face = ""
14 b = base64.b64decode(font_face)
15 with open('shixi.ttf', 'wb') as f:
16 f.write(b)
17 #处理字体问题,返回字体对应的字典
18 def font_dict():
19 font = TTFont('shixi.ttf')
20 font.saveXML('shixi.xml')
21 ccmap = font['cmap'].getBestCmap()
22 print("ccmap:\n",ccmap)
23 newmap = {}
24 for key,value in ccmap.items():
25 # value = int(re.search(r'(\d+)', ccmap[key]).group(1)) - 1
26 #转换成十六进制
27 key = hex(key)
28 value = value.replace('uni','')
29 a = 'u'+'0' * (4-len(value))+value
30 newmap[key] = a
31 print("newmap:\n",newmap)
32 #删除第一个没用的元素
33 newmap.pop('0x78')
34 #加上前缀u变成unicode....
35 for i,j in newmap.items():
36 newmap[i] = eval("u" + "\'\\" + j + "\'")
37 print("newmap:\n",newmap)
38
39 new_dict = {}
40 #根据网页上显示的字符样式改变键值对的显示
41 for key, value in newmap.items():
42 key_ = key.replace('0x', '&#x')
43 new_dict[key_] = value
44
45 return new_dict
46
47 #开始爬取,替换字体
48 def crawl(url,new_dict):
49 headers = {
50 'User_Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
51 }
52 response = requests.get(url, headers=headers)
53 # print(response.text)
54 html = response.text
55 # print(new_dict)
56 #测试这个font-face是不是对的
57
58 for key,value in new_dict.items():
59 if key in html:
60 html = html.replace(key,value)
61 # print('yes')
62 else:
63 pass
64 # print('no')
65 # print(html)
66 html = etree.HTML(html)
67 result = html.xpath("//ul[@class='position-list']//li")
68
69 #获取职位名称,地址,公司名称,薪水,链接
70 result_data = []
71 for element in result:
72 data = {}
73 try:
74 link = 'https://www.shixiseng.com'+element.xpath(".//div[1]//div[1]//a/@href")[0]
75 position_name = element.xpath(".//div[1]//div[1]//a/text()")[0]
76 company_name = element.xpath(".//div[1]//div[2]//a/text()")[0]
77 location = element.xpath(".//div[2]//div[1]/text()")[0]
78 salary = element.xpath(".//div[2]//div[2]//span[1]/text()")[0]
79 week = element.xpath(".//div[2]//div[2]//span[2]/text()")[0]
80 month = element.xpath(".//div[2]//div[2]//span[3]/text()")[0]
81 except:
82 print('wrong!')
83 print(position_name,location,company_name,salary,link,week,month)
84 data['position_name'] = position_name
85 data['company_name'] = company_name
86 data['location'] = location
87 data['salary'] = salary
88 data['week'] = week
89 data['month'] = month
90 data['link'] = link
91 result_data.append(data)
92 print(result_data)
93 return result_data
94 if __name__ == '__main__':
95 url = 'https://www.shixiseng.com/interns?k=Python&p='
96 parse_ttf()
97 data = font_dict()
98 print(data)
99 result = []
100 for i in range(2):
101 result.extend(crawl(url+str(i+1),data))
102 print(result)

font-face会经常变化,这就需要及时更新这个数据。

欢迎指正。

python爬取实习僧招聘信息字体反爬的更多相关文章

  1. 用python抓取智联招聘信息并存入excel

    用python抓取智联招聘信息并存入excel tags:python 智联招聘导出excel 引言:前一阵子是人们俗称的金三银四,跳槽的小朋友很多,我觉得每个人都应该给自己做一下规划,根据自己的进步 ...

  2. 用Python爬取智联招聘信息做职业规划

    上学期在实验室发表时写了一个爬取智联招牌信息的爬虫. 操作流程大致分为:信息爬取——数据结构化——存入数据库——所需技能等分词统计——数据可视化 1.数据爬取 job = "通信工程师&qu ...

  3. python之scrapy爬取某集团招聘信息以及招聘详情

    1.定义爬取的字段items.py # -*- coding: utf-8 -*- # Define here the models for your scraped items # # See do ...

  4. python之crawlscrapy爬取某集团招聘信息以及招聘详情

    针对这种招聘信息,使用crawlscrapy很适合. 1.settings.py # -*- coding: utf-8 -*- # Scrapy settings for gosuncn proje ...

  5. node.js 89行爬虫爬取智联招聘信息

    写在前面的话, .......写个P,直接上效果图.附上源码地址  github/lonhon ok,正文开始,先列出用到的和require的东西: node.js,这个是必须的 request,然发 ...

  6. python爬虫---CrawlSpider实现的全站数据的爬取,分布式,增量式,所有的反爬机制

    CrawlSpider实现的全站数据的爬取 新建一个工程 cd 工程 创建爬虫文件:scrapy genspider -t crawl spiderName www.xxx.com 连接提取器Link ...

  7. python爬虫爬取腾讯招聘信息 (静态爬虫)

    环境: windows7,python3.4 代码:(亲测可正常执行) import requests from bs4 import BeautifulSoup from math import c ...

  8. python之scrapy爬取某集团招聘信息

    1.创建工程 scrapy startproject gosuncn 2.创建项目 cd gosuncn scrapy genspider gaoxinxing gosuncn.zhiye.com 3 ...

  9. Python爬虫入门教程 64-100 反爬教科书级别的网站-汽车之家,字体反爬之二

    说说这个网站 汽车之家,反爬神一般的存在,字体反爬的鼻祖网站,这个网站的开发团队,一定擅长前端吧,2019年4月19日开始写这篇博客,不保证这个代码可以存活到月底,希望后来爬虫coder,继续和汽车之 ...

随机推荐

  1. 自由导入你的增量数据-根据条件将sqlserver表批量生成INSERT语句的存储过程实施笔记

    文章标题: 自由导入你的增量数据-根据条件将sqlserver表批量生成INSERT语句的存储过程增强版 关键字 : mssql-scripter,SQL Server 文章分类: 技术分享 创建时间 ...

  2. updatexml和extractvalue函数报错注入

    updatexml()函数报错注入 updatexml (XML_document, XPath_string, new_value); 第一个参数:XML_document是String格式,为XM ...

  3. [loj3364]植物比较

    结论:设$b_{i}$满足该限制,则$a_{i}$合法当且仅当$\forall i\ne j,a_{i}\ne a_{j}$且$\forall |i-j|<k,[a_{i}<a_{j}]= ...

  4. [nowcoder5666B]Infinite Tree

    首先考虑由$1!,2!,...,n!$所构成的虚树的一些性质: 1.每一个子树内所包含的阶乘的节点都是一个连续的区间(证明:对于子树k,如果存在$x!$和$y!$,即说明$x!$和$y!$的前$\de ...

  5. 关于postman的接口登录验证问题

    1.shiro的接口登录问题 碰到需要接口登录验证的:访问项目接口地址login,找到cookie将Cookie数据放入postman的headers 中. 2.碰到 security的项目.首先把相 ...

  6. 简单聊下.NET6 Minimal API的使用方式

    前言 随着.Net6的发布,微软也改进了对之前ASP.NET Core构建方式,使用了新的Minimal API模式.之前默认的方式是需要在Startup中注册IOC和中间件相关,但是在Minimal ...

  7. CF1559D2 Mocha and Diana (Hard Version)

    考虑到加树边每次最多只导致一对联通块之间的状态. 所以我们以任意顺序加入当前的合法边. 我们考虑先加入所有可加的\((1,a)\) 然后统计只在\(A\)中与1连的点,\(B\)中与2连的点. 则他们 ...

  8. 01 eclipse搭建maven的web工程(3.1)

    eclipse搭建maven的web工程(3.1) 一.下载并在eclipse安装JDK环境[查看] 二.下载并在eclipse安装maven环境[查看] 三.新建maven-webapp工程: 1. ...

  9. Spring DAO

    Spring DAO 连接池 使用JDBC访问数据库是,频繁的打开连接和关闭连接,造成性能影响,所以有了连接池.数据库连接池负责分配.管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接, ...

  10. Webpack 打包 Javascript 详细介绍

    本篇我们主要介绍Webpack打包 Javascript.当然,除了可以打包Javascript之外,webpack还可以打包html.但是这不是我们本篇的重点.我们可以参考 Webpack HTML ...