概述
Crawler--09: Anti-Crawling-Mechanismus
- 一、ua反爬
- 二、IP反爬
- 1、相关网址
- 2、ip反爬
- 三、图形验证码反扒
- 1、解决办法
- 2、tesseract 的使用
- 安装
- 3、复杂验证码图片
- 4、字体反爬
- 5、JS反爬
- 1.环境搭建
- 2.安装js代码调试工具
- 3. 安装PyExecJs模块
一、ua反爬
- 爬虫中非常重要的一种反反爬策略
- user-agent 用户代理
- Fake_useragent模块
- 安装Fake_useragent模块
pip install fake_useragent
- 随机ua的使用
ua = UserAgent()
s = ua.random
print(s)
二、IP反爬
1、相关网址
- 返回当前的ip地址
- http://httpbin.org/ip
- 查看当前的ip地址
- https://www.ipip.net/
- 比较好用的ip代理平台
- https://h.wandouip.com/member/index
2、ip反爬
- 有些网站会检测ip在同一时间内的访问次数,如果过于频繁,会封禁当前ip
- 解决办法:设置代理ip
- 在
requests
模块中,有一个参数proxies
来设置代理ip - 相关代理ip网站上的免费ip不好使
- 付费的代理ip不会用
- 通过cmd(windows)命令行内输入
ipconfig
来查看电脑的内部的ip地址 - 查看上网IP:使用IPIP网站查看电脑的上网IP
- 在
- 推荐代理网站
- 豌豆代理:https://www.wandouip.com/?wd=2020094010&e_matchtype=bdpc&bd_vid=9725195936188658607
- 注册
- 点击ip白名单,添加外网ip
- 选择提取api,生成api连接,复制api
- 豌豆代理:https://www.wandouip.com/?wd=2020094010&e_matchtype=bdpc&bd_vid=9725195936188658607
import random
import requests
# 设置代理
# proxy = {
# 'http':'114.98.162.196:9999'
# }
# url = 'http://www.httpbin.org/ip'
# res = requests.get(url, proxies=proxy)
# print(res.text)
ips = [
('223.240.244.48:23564'),
('121.233.226.191:5412'),
('114.100.3.87:766'),
('58.219.59.76:5412'),
('180.113.10.47:894'),
('27.40.111.110:36410'),
('42.56.3.242:766'),
('180.113.12.163:5412'),
('113.237.243.46:3617'),
('58.219.59.129:36410'),
('223.240.242.44:5412'),
('117.60.239.133:5412'),
('114.97.199.48:3617'),
('163.179.204.157:3617'),
('180.125.97.143:894'),
('60.174.190.152:23564'),
('49.86.177.230:36410'),
('182.101.237.158:5412'),
('114.98.139.136:23564'),
('114.225.241.237:23564'),
]
url = 'http://www.httpbin.org/ip'
for i in range(20):
try:
ip = random.choice(ips)
res = requests.get(url, proxies={'http':ip}, timeout=0.5)
print(res.text)
except Exception as e:
print('出现错误!',e)
- 快代理
- https://www.kuaidaili.com
- 语法格式:
proxies = {'协议':'协议://用户名:密码@ip:端口号'}
import requests
url = 'http://www.httpbin.org/ip'
proxies = {
'http': 'http://1550023517:8ktcozrp@114.215.174.98:16817',
'https': 'http://1550023517:8ktcozrp@114.215.174.98:16817'
}
result = requests.get(url, proxies=proxies)
print(result.text)
- 开放代理
import requests
class ProxyPool():
def __init__(self):
self.proxy_url = 'http://dev.kdlapi.com/api/getproxy/?orderid=992045485987175&num=100&protocol=2&method=1&an_ha=1&sep=2'
self.test_url = 'https://www.baidu.com/'
self.headers = {
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_3_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36'
}
def get_prosy_pool(self):
html = requests.get(url=self.proxy_url, headers=self.headers).text
proxy_list = html.split('n')
# print(proxy_list)
for prosy in proxy_list:
self.test_proxy(prosy)
def test_proxy(self, prosy):
proxies = {
'http':'{}'.format(prosy),
'https':'{}'.format(prosy)
}
try:
res = requests.get(url=self.test_url, proxies=proxies, headers=self.headers, timeout=1)
if res.status_code == 200:
print(prosy,'可以用!')
except Exception as e:
print(prosy,'不能用!')
def main(self):
self.get_prosy_pool()
if __name__ == '__main__':
spider = ProxyPool()
spider.main()
三、图形验证码反扒
1、解决办法
- 通过算以及深度学习解决
- tesseracct解决
- 阻碍我们爬虫的有时候正式在登陆过或者请求 一些数据时候的图形验证码。因此我们需要一种可以将图片翻译成文字的技术。将图片翻译成文字一般称为光学文字识别(Optical Character Recognition),简称OCR。实现OCR的开源运行库不多。因为存在一些技术壁垒(需要大量的数据、算法、机械学习、深度学习知识等),如果做的很好,就具有很高的商业价值。因此开源的比较少。这里介绍一种优秀的图像识别开源库:Tesseract.
- Tesseract是一个将图像翻译成文字的OCR(光学文字识别,Optical Character Recognition),目前由谷歌赞助。Tesseract是目前公认最优秀、最准确的开源OCR库。Tesseract具有很高的识别度,也具有很高的灵活性,他可以通过训练识别任何字体
- Windows系统安装 在以下链接下载可执行文件,https://github.com/tesseract-ocr/
- 阻碍我们爬虫的有时候正式在登陆过或者请求 一些数据时候的图形验证码。因此我们需要一种可以将图片翻译成文字的技术。将图片翻译成文字一般称为光学文字识别(Optical Character Recognition),简称OCR。实现OCR的开源运行库不多。因为存在一些技术壁垒(需要大量的数据、算法、机械学习、深度学习知识等),如果做的很好,就具有很高的商业价值。因此开源的比较少。这里介绍一种优秀的图像识别开源库:Tesseract.
- 打码平台
- selnium模拟处理
2、tesseract 的使用
安装
- 将安装的路径添加到path环境变量内
- 需要把训练的数据添加到用户变量内
- 安装模块
pip install pytesseract
- 使用
- tesseract demo.jpg text
- demo.jpg是识别的图片
- text是返回的结果
import pytesseract
from PIL import Image # 图像处理库
pytesseract.pytesseract.tesseract_cmd = r'C:Program Files (x86)Tesseract-OCRtesseract.exe' # 指定tesseract驱动
tessdata_dir_config = r'--tessdata-dir "C:Program Files (x86)Tesseract-OCRtessdata"' # 指定tesseract训练数据路径
image = Image.open('a.jpg')
print(pytesseract.image_to_string(image, lang='eng', config=tessdata_dir_config))
3、复杂验证码图片
- 1.行为验证反爬(例如滑块验证码图片)
- 解决方法:selenium内的鼠标行为链
- 思路:
- 找到一个固定的点,例如150然后一次一次的拖动尝试,直到图片和缺口吻合
QQ空间滑块验证码代码演示
- 找到一个固定的点,例如150然后一次一次的拖动尝试,直到图片和缺口吻合
from selenium import webdriver
import time
from selenium.webdriver import ActionChains
driver = webdriver.Chrome()
def login():
driver.get('https://i.qq.com/')
time.sleep(3)
# 切换iframe
driver.switch_to_frame(driver.find_element_by_id('login_frame'))
# 切换登陆方式
driver.find_element_by_id('switcher_plogin').click()
time.sleep(3)
# 输入账号和密码
driver.find_element_by_id('u').send_keys('1550023517')
time.sleep(3)
driver.find_element_by_id('p').send_keys('wangjiaxin.....')
time.sleep(3)
driver.find_element_by_id('login_button').click()
time.sleep(3)
# 创建鼠标行为链对象
actions = ActionChains(driver)
# 切换ifame
driver.switch_to_frame(driver.find_element_by_id('tcaptcha_iframe'))
# 偏移量
x = 160
# 按下拖动
while True:
try:
# 定位拖动按钮
tcaptcha_drag_thumb = driver.find_element_by_id('tcaptcha_drag_thumb')
# 按下拖动
actions.drag_and_drop_by_offset(tcaptcha_drag_thumb, xoffset=x, yoffset=0).perform()
x += 5
except Exception:
break
login()
- 2.12306图片验证码的解决
- 打码平台的使用:超级鹰
- 1 注册账号
- 2 重置
- 3 创建软件ID,点击生成软件ID
- 4 下载开发文档实例代码
- 实现步骤
- 目标url:12306
- 核心技术:selenium+鼠标行为链
- 思路:
- 1 通过selenium加载整个页面
- 2 获取验证码图片
- 3 将图片提交给超级鹰
- 4 返回验证码图片的结果(识别结果就是一个或者多个图片的坐标值)
- 5 通过坐标值,来进行正确的点击
- 第一步:selenium加载整个页面
- 第二步:对页面进行保存
- 第三步:截取12306验证码图片
- 第四步:交给超级鹰进行识别,返回正确的坐标值
- 第五步:根据正确的坐标值进行点击动作
- 打码平台的使用:超级鹰
12306图片验证码登陆代码演示
import requests
from hashlib import md5
from selenium import webdriver
import time
from selenium.webdriver import ActionChains
from PIL import Image
class Chaojiying_Client(object):
def __init__(self, username, password, soft_id):
self.username = username
password = password.encode('utf8')
self.password = md5(password).hexdigest()
self.soft_id = soft_id
self.base_params = {
'user': self.username,
'pass2': self.password,
'softid': self.soft_id,
}
self.headers = {
'Connection': 'Keep-Alive',
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
}
def PostPic(self, im, codetype):
"""
im: 图片字节
codetype: 题目类型 参考 http://www.chaojiying.com/price.html
"""
params = {
'codetype': codetype,
}
params.update(self.base_params)
files = {'userfile': ('ccc.jpg', im)}
r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers)
return r.json()
def ReportError(self, im_id):
"""
im_id:报错题目的图片ID
"""
params = {
'id': im_id,
}
params.update(self.base_params)
r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
return r.json()
# if __name__ == '__main__':
# chaojiying = Chaojiying_Client('15840039263', 'wangjiaxin.....', '916503') #用户中心>>软件ID 生成一个替换 96001 # 916503
# im = open('code2.png', 'rb').read() #本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
# print(chaojiying.PostPic(im, 9004)['pic_str'])
drvier = webdriver.Chrome()
# 加载页面
drvier.get('https://kyfw.12306.cn/otn/resources/login.html')
time.sleep(3)
# 切换登陆方式
drvier.find_element_by_xpath('/html/body/div[2]/div[2]/ul/li[2]/a').click()
time.sleep(3)
drvier.maximize_window()
time.sleep(3)
drvier.find_element_by_id('J-userName').send_keys('15840039263')
time.sleep(3)
drvier.find_element_by_id('J-password').send_keys('Wjx19972')
time.sleep(3)
# 保存加载后的页面
drvier.save_screenshot('code.png')
# 定位图片
cod_img_element = drvier.find_element_by_class_name('imgCode')
location = cod_img_element.location # location的返回值是一个字典(是图片左上角的坐标值)
size = cod_img_element.size # size就是图片的宽度和高度
# 获取左上角和右下角的坐标
rangle = (int(location['x']), int(location['y']), int(location['x']+size['width']), int(location['y']+size['height']))
# 12306验证码图片的裁剪
i = Image.open('code.png')
code_img_name = 'yzm.png'
frame = i.crop(rangle) # crop() 根据指定的区域进行裁剪
frame.save(code_img_name)
# 将验证码土图片交给超级鹰进行识别
chaojiying = Chaojiying_Client('15840039263', 'wangjiaxin.....', '916503') #用户中心>>软件ID 生成一个替换 96001 # 916503
im = open('yzm.png', 'rb').read() #本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
print(chaojiying.PostPic(im, 9004)['pic_str'])
result = chaojiying.PostPic(im, 9004)['pic_str']
all_list = [] # 存储被点击的坐标 [[x,y],[x,y]]
if '|' in result: # 点击多次
lst1 = result.split('|') # split()分割方法
count1 = len(lst1)
for i in range(count1):
xy_list = []
x = int(lst1[i].split(',')[0])
y = int(lst1[i].split(',')[1])
xy_list.append(x)
xy_list.append(y)
all_list.append(xy_list)
else: # 点击一次
xy_list = []
x = int(result.split(',')[0])
y = int(result.split(',')[1])
xy_list.append(x)
xy_list.append(y)
all_list.append(xy_list)
# 对列表元素中的xy进行点击
for l in all_list:
x = l[0]
y = l[1]
# 将参照物移动到验证码图片上,进行点击
ActionChains(drvier).move_to_element_with_offset(cod_img_element, x, y).click().perform()
time.sleep(5)
drvier.find_element_by_id('J-login').click()
总结
1、打码平台的使用
* 1、注册账号
* 2、充值
* 3、创建软件id、点击生成软件ID
* 4、下载开发文档实例代码
2、鼠标行为链的使用
http://selenium-python.readthedocs.io/api.html
特殊使用的方法
# 定位图片
cod_img_element = drvier.find_element_by_class_name('imgCode')
location = cod_img_element.location # location的返回值是一个字典(是图片左上角的坐标值)
size = cod_img_element.size # size就是图片的宽度和高度
# 获取左上角和右下角的坐标
rangle = (int(location['x']), int(location['y']), int(location['x']+size['width']), int(location['y']+size['height']))
# 将参照物移动到验证码图片上,进行点击
ActionChains(drvier).move_to_element_with_offset(cod_img_element, x, y).click().perform()
time.sleep(5)
4、字体反爬
- 字体反扒也称之为CSS反爬
- 这个字体是隐藏在我们CSS文件中的一个.ttf文件中
- 字体反爬的原理
- 开发者创建了一种字体代号,在网页中就显示的这种字体代号
- 如何解决
- 1、先找到.ttf文件
- 2、转换成其他格式的文件(例如:xml文件)
- 3、分析xml文件(推荐使用工具:FontCreator)
- 4、找出字体对应的映射关系和真事字体进行替换
案例演示
需求:
爬取论坛内的文本
目标url:https://club.autohome.com.cn/bbs/thread/16299a4708f8bb7f/96134998-1.html
总结:
font = TTFont('wKgHFVsUz2eAJ12kAABj8AY7vEo97..ttf')
font.saveXML('fonts.xml')
# 构建编码列表,获取xml文件当中的name的值 找到映射关系
uni_list = []
unilist = font.getGlyphOrder()
for i in unilist[1:]:
# r = r'u' + i[3:]
r = eval(r"'u" + i[3:] + "'")
uni_list.append(r)
# 替换
work_list = ['七', '更', '一', '高', '和', '近', '的', '下', '三', '低', '很', '五', '十', '右', '左', '少', '呢', '多', '大', '着', '九', '是', '二', '坏', '地', '长', '上', '矮', '了', '不', '短', '远', '六', '八', '四', '得' ,'好' ,'小']
for i in range(len(work_list)):
content_str = content_str.replace(uni_list[i],work_list[i])
print(content_str)
代码演示
import requests
from lxml import etree
from fontTools.ttLib import TTFont #
url = 'https://club.autohome.com.cn/bbs/thread/16299a4708f8bb7f/96134998-1.html'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36'
}
res = requests.get(url=url, headers=headers)
res_html = res.text
html = etree.HTML(res_html)
content_list = html.xpath('//div[@class="tz-paragraph"]//text()')
# 将列表中的数据以空格链接数据
content_str = ''.join(content_list)
# print(content_str)
font = TTFont('wKgHFVsUz2eAJ12kAABj8AY7vEo97..ttf')
font.saveXML('fonts.xml')
'''
构建一个编码的列表
构建一个字体的列表
编码与字体一一对应(映射关系)
'''
# 构建编码列表,获取xml文件当中的name的值
uni_list = []
unilist = font.getGlyphOrder()
for i in unilist[1:]:
# r = r'u' + i[3:]
r = eval(r"'u" + i[3:] + "'")
uni_list.append(r)
# print(uni_list)
'''
eval()用来执行的是一个字符串表达式,并返回表达式的的值
可以把字符串转化成列表、元组、字典
'''
work_list = ['七', '更', '一', '高', '和', '近', '的', '下', '三', '低', '很', '五', '十', '右', '左', '少', '呢', '多', '大', '着', '九', '是', '二', '坏', '地', '长', '上', '矮', '了', '不', '短', '远', '六', '八', '四', '得' ,'好' ,'小']
for i in range(len(work_list)):
content_str = content_str.replace(uni_list[i],work_list[i])
print(content_str)
5、JS反爬
1.环境搭建
- 安装node.js
- 下载网站:https://nodejs.org/en/download/
- windows系统node.js的安装与环境配置参考:https://blog.csdn.net/qq_41465646/article/details/107656044
- macOS系统的node.js的安装与环境配置参考:https://www.jianshu.com/p/3e59aebb6a76
2.安装js代码调试工具
- 发条js调试工具
3. 安装PyExecJs模块
pip install PyExecJs -i https://pypi.douban.com/simple
最后
以上就是还单身啤酒为你收集整理的爬虫--09:反爬机制一、ua反爬二、IP反爬三、图形验证码反扒的全部内容,希望文章能够帮你解决爬虫--09:反爬机制一、ua反爬二、IP反爬三、图形验证码反扒所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复