python爬取实习僧招聘信息字体反爬
参考博客: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爬取实习僧招聘信息字体反爬的更多相关文章
- 用python抓取智联招聘信息并存入excel
用python抓取智联招聘信息并存入excel tags:python 智联招聘导出excel 引言:前一阵子是人们俗称的金三银四,跳槽的小朋友很多,我觉得每个人都应该给自己做一下规划,根据自己的进步 ...
- 用Python爬取智联招聘信息做职业规划
上学期在实验室发表时写了一个爬取智联招牌信息的爬虫. 操作流程大致分为:信息爬取——数据结构化——存入数据库——所需技能等分词统计——数据可视化 1.数据爬取 job = "通信工程师&qu ...
- python之scrapy爬取某集团招聘信息以及招聘详情
1.定义爬取的字段items.py # -*- coding: utf-8 -*- # Define here the models for your scraped items # # See do ...
- python之crawlscrapy爬取某集团招聘信息以及招聘详情
针对这种招聘信息,使用crawlscrapy很适合. 1.settings.py # -*- coding: utf-8 -*- # Scrapy settings for gosuncn proje ...
- node.js 89行爬虫爬取智联招聘信息
写在前面的话, .......写个P,直接上效果图.附上源码地址 github/lonhon ok,正文开始,先列出用到的和require的东西: node.js,这个是必须的 request,然发 ...
- python爬虫---CrawlSpider实现的全站数据的爬取,分布式,增量式,所有的反爬机制
CrawlSpider实现的全站数据的爬取 新建一个工程 cd 工程 创建爬虫文件:scrapy genspider -t crawl spiderName www.xxx.com 连接提取器Link ...
- python爬虫爬取腾讯招聘信息 (静态爬虫)
环境: windows7,python3.4 代码:(亲测可正常执行) import requests from bs4 import BeautifulSoup from math import c ...
- python之scrapy爬取某集团招聘信息
1.创建工程 scrapy startproject gosuncn 2.创建项目 cd gosuncn scrapy genspider gaoxinxing gosuncn.zhiye.com 3 ...
- Python爬虫入门教程 64-100 反爬教科书级别的网站-汽车之家,字体反爬之二
说说这个网站 汽车之家,反爬神一般的存在,字体反爬的鼻祖网站,这个网站的开发团队,一定擅长前端吧,2019年4月19日开始写这篇博客,不保证这个代码可以存活到月底,希望后来爬虫coder,继续和汽车之 ...
随机推荐
- Linux 软连接与硬连接 区别
先说结论 软连接相当于快捷方式,访问软连接会被替换为其指向的绝对路径,如果其指向的文件被删除,则无法访问. 硬连接相当于指针,与它指向的文件都指向相同的inode,当其指向的文件被删除,inode由于 ...
- Spark SQL知识点大全与实战
Spark SQL概述 1.什么是Spark SQL Spark SQL是Spark用于结构化数据(structured data)处理的Spark模块. 与基本的Spark RDD API不同,Sp ...
- [loj3146]路灯
显然,能从$l$到$r$当且仅当$[l,r)$中的灯全部都亮,以下不妨令询问的$r$全部减1 当修改节点$x$时,找到包含$x$的极大的灯(除$x$以外)全部都亮的区间$[l,r]$,即令$l_{0} ...
- [bzoj1416]神奇的口袋
容易发现操作任意次并不会改变每一个点的概率(因为每一个点加d的概率相同,期望与原数成比例),然后直接输出即可(要用高精度) 1 #include<bits/stdc++.h> 2 usin ...
- vue-if和show
<template> <div> <div v-if="flag">今晚要上课</div> <div v-else> 今 ...
- Jenkins快速上手安装
目录 环境准备 - JDK 安装 1. APT 安装 2. WAR包方式运行 3.Docker 方式运行 Jenkins 是一个独立的开源自动化服务器,可以用来自动化与构建.测试.交付或部署软件相关的 ...
- freeswitch APR库哈希表
概述 freeswitch的核心源代码是基于apr库开发的,在不同的系统上有很好的移植性. 哈希表在开发中应用的非常广泛,主要场景是对查询效率要求较高的逻辑,是典型的空间换时间的数据结构实现. 大多数 ...
- 了解Threejs中的Clock对象以及简单应用
什么是Clock对象 如果你对 JavaScript 有一定了解,那么 JavaScript 的时间对象 Date 你一定不陌生,Clock 本质上就是对 Date 进行封装,提供了一些方法和属性 当 ...
- ABC201题解
因为学校的某些操作. 让最近两天的\(Atcoder\)都能打了,挺开心的. 想上次\(ABC\)看错题意,失败退场. ------------------------------ \(A\) 直接手 ...
- Codeforces 1422F - Boring Queries(树套树)
upd on 2021.9.5:昨天的那个版本被 2-tower 卡爆了,故今天重发一个. Codeforces 题面传送门 & 洛谷题面传送门 没往"每个数最多只有一个 \(> ...