我是靠谱客的博主 还单身啤酒,最近开发中收集的这篇文章主要介绍爬虫--09:反爬机制一、ua反爬二、IP反爬三、图形验证码反扒,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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
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/
  • 打码平台
  • 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空间滑块验证码代码演示
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反爬三、图形验证码反扒所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(68)

评论列表共有 0 条评论

立即
投稿
返回
顶部