spider【第五篇】常见的反爬手段和解决思路

反反爬的主要思路

1.尽可能的去模拟浏览器,浏览器在如何操作,代码中就如何去实现。

2.wap 和app的数据反反爬一般不厉害

通过headers字段来反爬

把headers的信息copy到程序的headers:如常见的User-Agent Content-type referer  Cookie   等字段

 

通过User-Agent字段反爬的话,只需要给他在请求之前添加User-Agent即可,更好的方式是使用User-Agent池来解决,我们可以考虑收集一堆User-Agent的方式,或者是随机生成User-Agent

import random

def get_ua():
    first_num = random.randint(55, 62)
    third_num = random.randint(0, 3200)
    fourth_num = random.randint(0, 140)
    os_type = [
        '(Windows NT 6.1; WOW64)', '(Windows NT 10.0; WOW64)', '(X11; Linux x86_64)',
        '(Macintosh; Intel Mac OS X 10_12_6)'
    ]
    chrome_version = 'Chrome/{}.0.{}.{}'.format(first_num, third_num, fourth_num)

    ua = ' '.join(['Mozilla/5.0', random.choice(os_type), 'AppleWebKit/537.36',
                   '(KHTML, like Gecko)', chrome_version, 'Safari/537.36']
                  )
    return ua
random_ua

通过js来反爬

在请求目标网站的时候,我们看到的似乎就请求了一个网站,然而实际上在成功请求目标网站之前,中间可能有通过js实现的跳转,我们肉眼不可见,这个时候可以通过点击perserve log按钮实现观察页面跳转情况

在这些请求中,如果请求数量很多,一般来讲,只有那些response中带cookie字段的请求是有用的,意味着通过这个请求,对方服务器有设置cookie到本地

通过js生成了请求参数

对应的需要分析js,观察加密的实现过程。学习了selenium这个问题会变得很容易

通过js实现了数据的加密

对应的需要分析js,观察加密的实现过程,学习了selenium这个问题会变得很容易

通过验证码来反爬

通过打码平台或者是机器学习的方法识别验证码,其中打码平台廉价易用,更值得推荐,后面的课程回来学习如何使用

通过ip地址来反爬

同一个ip大量请求了对方服务器,有更大的可能性会被识别为爬虫,对应的通过购买高质量的ip的方式能够结局问题

通过账号来反爬

如果某些网站要求必须登录才能访问某些数据,那还可以检测账号的流量,可以通过注册多个账号来解决

selenium的使用

 Selenium是一个Web的自动化测试工具,最初是为网站自动化测试而开发的,Selenium 可以直接运行在浏览器上,它支持所有主流的浏览器(包括PhantomJS这些无界面的浏览器),可以接收指令,让浏览器自动加载页面,获取需要的数据,甚至页面截屏

PhantomJS

是一个基于Webkit的“无界面”(headless)浏览器,它会把网站加载到内存并执行页面上的 JavaScript

下载地址:http://phantomjs.org/download.html

Chromedriver的介绍

Chromedriver 也是一个能够被selenium驱动的浏览器,但是和PhantomJS的区别在于它是有界面的

下载地址:https://npm.taobao.org/mirrors/chromedriver

selenium的入门使用

掌握如何发送请求,加载网页
掌握如何进行简单的元素定位
掌握如何从获取浏览器中的数据

加载网页: selenium通过控制浏览器,所以对应的获取的数据都是elements中的内容

  from selenium import webdriver 
  driver = webdriver.PhantomJS(“c:…/pantomjs.exe”)  # pantomjs安装的位置
  driver.get("http://www.baidu.com/")

定位和操作

 find_element_by_id (返回一个元素)
  find_elements_by_xpath (返回一个包含元素的列表)
  find_elements_by_link_text (根据连接文本获取元素列表)
  find_elements_by_partial_link_text (根据连接包含的文本获取元素列表)
  find_elements_by_tag_name (根据标签名获取元素列表)
  find_elements_by_class_name (根据类名获取元素列表)

查看请求信息:  

  driver.page_source
  driver.get_cookies()
  driver.current_url

退出

  driver.close() #退出当前页面
  driver.quit()  #退出浏览器
from selenium import webdriver

driver = webdriver.Chrome(executable_path="E:/webdriver/chromedriver.exe")

driver.get("https://www.douban.com/")

ret1 = driver.find_element_by_id("anony-nav")
print(ret1)
# 输出为:<selenium.webdriver.remote.webelement.WebElement (session="ea6f94544ac3a56585b2638d352e97f3", element="0.5335773935305805-1")>

ret2 = driver.find_elements_by_id("anony-nav")
print(ret2)
# 输出为:[<selenium.webdriver.remote.webelement.WebElement (session="ea6f94544ac3a56585b2638d352e97f3", element="0.5335773935305805-1")>]

ret3 = driver.find_elements_by_xpath("//*[@id='anony-nav']/h1/a")
print(len(ret3))
# 输出为:1

ret4 = driver.find_elements_by_tag_name("h1")
print(len(ret4))
# 输出为:1

ret5 = driver.find_elements_by_link_text("下载豆瓣 App")
print(len(ret5))
# 输出为:1

ret6 = driver.find_elements_by_partial_link_text("豆瓣")
print(len(ret6))
# 输出为:24

driver.close()
示例

selenium的高级使用

使用selenium切换switch_to_window

手动打开一个chrome界面,先手动操作一下(因为代码很难模拟)

1. 打开chrome在cmd运行如下命令 
chrome.exe --remote-debugging-port=9222 --user-data-dir="C:\selenum\AutomationProfile"

2.利用第一步打开的浏览器继续操作

import time
from selenium import webdriver
from newdex_lastprice import get_last_pirce

# options = webdriver.ChromeOptions()
# options.add_extension(
#     "C:\\Users\ZXZ\AppData\Local\Google\Chrome\\User Data\Default\Extensions\\ammjpmhgckkpcamddpolhchgomcojkle\\6.2.0_0.crx")

chrome_options = webdriver.ChromeOptions()
chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")

driver = webdriver.Chrome(executable_path="E:/webdriver/chromedriver.exe", options=chrome_options)
print(driver.title)
main_window = driver.current_window_handle


def trade(last_pirce, volume, side):
    print('start {}'.format(side))

    buy_tag = driver.find_element_by_id('pane-first').find_element_by_class_name(side)

    input_tags = buy_tag.find_elements_by_class_name('place-order-info-input')
    price_buy_tag = input_tags[0].find_element_by_tag_name('input')
    volume_buy_tag = input_tags[1].find_element_by_tag_name('input')
    button_bug = buy_tag.find_element_by_tag_name('button')

    price_buy_tag.clear()
    volume_buy_tag.clear()
    price_buy_tag.send_keys(str(last_pirce))
    volume_buy_tag.send_keys(str(volume))
    button_bug.click()

    print(driver.current_window_handle)

    time.sleep(10)

    if len(driver.window_handles) > 1:
        sub_handle = driver.window_handles[1]  # 获取所有窗口句柄
        driver.switch_to_window(sub_handle)
        print(driver.current_window_handle)

        driver.find_element_by_class_name('actions').find_elements_by_tag_name('button')[1].click()
        print(666)
        if len(driver.window_handles) > 1:
            driver.close()

    time.sleep(10)
    driver.switch_to_window(main_window)


if __name__ == '__main__':
    while True:
        last_pirce = 0.0043  # get_last_pirce() 需修改
        volume = 100  # 需修改

        trade(last_pirce, volume, 'buy')
        trade(last_pirce, volume, 'sell')
示例

使用selenium切换frame

frame是html中常用的一种技术,即一个页面中嵌套了另一个网页,selenium默认是访问不了frame中的内容的,对应的解决思路是 driver.switch_to.frame()

# coding=utf-8
from selenium import webdriver
import time

driver = webdriver.Chrome(executable_path="E:/webdriver/chromedriver.exe")

driver.get("https://mail.qq.com/")

driver.switch_to.frame("login_frame")
driver.find_element_by_id("u").send_keys("598779784@qq.com")
driver.find_element_by_id("p").send_keys("liu1314@.qq")
driver.find_element_by_id("login_button").click()


driver.quit()
模拟登陆qq邮箱
__author__ = 'hy'
import time
from selenium import webdriver

browser = webdriver.Chrome(executable_path="E:/webdriver/chromedriver.exe")
#
browser.get("https://www.zhihu.com/signin")
time.sleep(2)

# 点击QQ
# browser.find_element_by_css_selector(".qrcode-signin-cut-button").click()
browser.find_element_by_css_selector(".Login-socialLogin").click()
time.sleep(2)
browser.find_elements_by_tag_name("g")[-1].click()
time.sleep(5)

browser.switch_to.window(browser.window_handles[-1])
browser.switch_to.frame("ptlogin_iframe")  # iframe必须逐级切入

# 用户名 密码

# 隐藏初始界面
browser.execute_script('document.getElementById("qlogin").style="display: none;"')
browser.execute_script('document.getElementsByClassName("authLogin").style="display: none;"')
# 显示用户、密码输入界面
browser.execute_script('document.getElementById("web_qr_login").style="display: block;"')
# browser.evaluate_script('document.getElementById("batch_quto").contentEditable = true')
time.sleep(5)

# 输入用户、密码
elem_user = browser.find_element_by_name("u").send_keys("598779784")
elem_pwd = browser.find_element_by_name("p").send_keys("598779784@qq.com")
elem_but = browser.find_element_by_id("login_button").click()
time.sleep(5)
QQ登录知乎

 QQ登录到第三方平台详解 https://github.com/ecithy/selenium-QQ

打码平台的使用

1.为什么需要了解打码平台的使用

现在很多网站都会使用验证码来进行反爬,所以为了能够更好的获取数据,需要了解如何使用打码平台爬虫中的验证码.

2.见的打码平台

云打码:http://www.yundama.com/

	能够解决通用的验证码识别

极验验证码智能识别辅助:http://jiyandoc.c2567.com/

	能够解决复杂验证码的识别

云打码的使用

import os
import time
import random
from selenium import webdriver
from PIL import Image

import requests
from bs4 import BeautifulSoup
from scripts.helper import YDMHelper


def set_header():
    '设置header'
    agent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:51.0) Gecko/20100101 Firefox/51.0"
    header = {
        "HOST": "testnet-faucet.mempool.co",
        "Origin": "testnet-faucet.mempool.co",
        "Referer": "https://testnet-faucet.mempool.co",
        'User-Agent': agent
    }
    return header


def get_token(url):
    resp = requests.get(url, url, headers=set_header())
    s1 = BeautifulSoup(resp.text, 'html.parser')
    token = s1.find(name='input', attrs={'name': 'tauth'}).get('value')
    return token


def get_image_url():
    r1 = requests.get(url, headers=set_header())
    s1 = BeautifulSoup(r1.text, 'html.parser')
    image_url = s1.find(name='form').find(name='img').get('src')
    return image_url


def pre_handle(filename):
    current_files = os.listdir()
    if filename in current_files:
        os.remove(filename)


if __name__ == '__main__':
    # 参数设置
    taddress_list = ['2NBMEXTKGxz5jyYGSPUXMrG3HxFap2PQK7i', '2NBMEXcuArNqkPJXV9ENuXjHSPtQcfm7mTA',
                     '2NBMEXLFktCYC5jWnBibky6CLUGWowVddqt']
    interval_list = [300, 500]
    taddress = random.choice(taddress_list)

    filename = 'code.png'
    url = 'https://testnet-faucet.mempool.co/'

    while True:
        try:
            driver = webdriver.Chrome(executable_path="E:/webdriver/chromedriver.exe")
            driver.maximize_window()
            # 删除上次的验证码文件
            pre_handle(filename)

            # 得到图片验证码
            image_url = url  # get_image_url()

            driver.get(image_url)
            element = driver.find_element_by_css_selector(".center").find_element_by_tag_name('img')  #
            driver.save_screenshot(filename)

            left = element.location['x'] + 30
            top = element.location['y'] + 80
            # right = element.location['x'] + element.size['width']
            # bottom = element.location['y'] + element.size['height']
            # left = 178
            # top = 488
            right = left + element.size['width'] + 30
            bottom = top + element.size['height'] + 10

            im = Image.open(filename)
            im = im.crop((left, top, right, bottom))  # x0, y0, x1, y1
            im.save(filename)
            time.sleep(2)  # 保存完再关闭

            captcha = YDMHelper.get_code(filename)
            if len(captcha) > 2:
                first_char, second_char, third_char = captcha[0], captcha[1], captcha[2]
                if first_char.isdigit() and third_char.isdigit():
                    print('再次运算')
                    if second_char.lower() == 'x':
                        captcha = int(first_char) * int(third_char)
                        print('乘法结果: {}'.format(captcha))

                    if second_char.lower() == '+' or second_char.lower() == 't':
                        captcha = int(first_char) + int(third_char)
                        print('加法结果: {}'.format(captcha))

                else:
                    driver.close()
                    time.sleep(interval_list[1])
                    continue

            driver.find_element_by_name("captcha").send_keys(captcha)
            driver.find_element_by_id('taddress').send_keys(taddress)
            driver.find_element_by_id('amount').send_keys('0.01')
            time.sleep(3)
            driver.find_elements_by_tag_name('input')[3].click()

            time.sleep(interval_list[1])
            driver.close()

        except Exception as e:
            print(e)
View Code
4.常见的验证码的种类
    4.1 url地址不变,验证码不变
        这是验证码里面非常简单的一种类型,对应的只需要获取验证码的地址,然后请求,通过打码平台识别即可

    4.2 url地址不变,验证码变化
        这种验证码的类型是更加常见的一种类型,对于这种验证码,大家需要思考:

        在登录的过程中,假设我输入的验证码是对的,对方服务器是如何判断当前我输入的验证码是显示在我屏幕上的验证码,而不是其他的验证码呢?

        在获取网页的时候,请求验证码,以及提交验证码的时候,对方服务器肯定通过了某种手段验证我之前获取的验证码和最后提交的验证码是同一个验证码,那这个手段是什么手段呢?

        很明显,就是通过cookie来实现的,所以对应的,在请求页面,请求验证码,提交验证码的到时候需要保证cookie的一致性,对此可以使用requests.session来解决

 

  

 

 

 

 

 

  

  

 

转载于:https://www.cnblogs.com/hyit/articles/10686940.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
遇到 `ModuleNotFoundError: No module named 'scrapyspider'` 这种错误通常是Python中尝试导入一个不存在的模块导致的。这个错误意味着你在代码中引用了一个名为 'scrapyspider' 的模块,但Python解释器找不到它。 为了解决这个问题,你可以按照以下步骤操作: 1. **检查拼写和大小写**:确保你输入的模块名 (`scrapyspider`) 在文件和导入语句中的拼写和大小写完全一致,因为Python是区分大小写的。 2. **安装模块**:如果你需要使用外部模块,确保已经通过pip安装了。在命令行或终端中运行 `pip install scrapyspider`(如果该模块存在)。如果模块名字有误,请替换为正确的包名。 3. **添加到sys.path**:如果模块在项目的其他位置,可能需要将那个路径添加到sys.path中,这样Python就能找到它。在你的程序开始处添加类似这样的代码: ```python import sys sys.path.append('/path/to/module') # 将你的模块目录替换为实际路径 ``` 4. **更新依赖**:如果你的项目使用了包管理工具(如virtualenv、conda或poetry),确保所有依赖都已更新并激活。 5. **检查版本冲突**:有时候,两个不同版本的库可能会导致相同名称的模块冲突,检查是否有这种情况并选择合适的版本。 6. **检查源码或仓库**:如果模块是你自己编写的,确认模块文件是否存在,并且在预期的路径下。 相关问题: 1. 什么是Python的sys.path,为什么在这里很重要? 2. 如何查看已经安装的Python模块? 3. 如果模块是自定义的,如何确保Python能够正确加载?

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值