CoderCastrov logo
CoderCastrov
AWS Lambda

AWS серверный парсинг: рандомизация вашего IP.

AWS серверный парсинг: рандомизация вашего IP.
просмотров
3 мин чтение
#AWS Lambda

Парсинг заключается в обмане веб-сайта, который вы хотите парсить, чтобы он думал, что вы не робот, а человек; отслеживание куки, периодическое изменение вашего пользовательского агента, установка случайных таймеров при отправке запросов... Все это веселые вещи, необходимые для парсинга веба. Но в наше время большинство сайтов, содержащих данные, которые стоит парсить, имеют некоторые инструменты защиты от ботов, которые обнаружат, что вы робот, практически после 10 запросов парсинга, поэтому нам приходится прибегать к священному граалю трюков для парсинга данных: смене IP.

Я люблю AWS, особенно серверные архитектуры, и считаю, что серверный парсинг - отличный способ парсить без больших затрат и хлопот по управлению сервером. Если вы не знаете, как настроить парсер с помощью AWS серверного парсинга, вы можете ознакомиться с следующим учебником:


Создание веб-скрейпера с использованием AWS Lambda и Serverless Framework

В этом руководстве я расскажу вам основы создания веб-скрейпера с использованием Node.js и AWS Lambda. Мой скрейпер будет...

medium.com

Теперь, когда вы знаете, как парсить без сервера, давайте начнем с переключения IP.

Код:

import boto3
import os
import json
import time

client = boto3.client('sqs')
natClient = boto3.client('ec2')
lambdaClient = boto3.client('lambda')

def reset(event, context):
    vpcId = ""
    subnetId = ""
    routetableId = ""

    # блокировка функций лямбда
    response = lambdaClient.put_function_concurrency(
        FunctionName='feiScraperEvent--dev',
        ReservedConcurrentExecutions=0
    )
    response = lambdaClient.put_function_concurrency(
        FunctionName='feiScraperContest--dev',
        ReservedConcurrentExecutions=0
    )
    response = lambdaClient.put_function_concurrency(
        FunctionName='feiScraperResult--dev',
        ReservedConcurrentExecutions=0
    )

    # удаление NAt-шлюза
    nat_gateway_id = natClient.describe_nat_gateways(
        Filters=[{
            'Name': 'vpcId',
            'Values': [vpcId]
        }]
    )
    for gateway in nat_gateway_id['NatGateways']:
        try:
            natClient.delete_nat_gateway(
                NatGatewayId=gateway['NatGatewayId']
            )
            natClient.release_address(
                AllocationId=gateway['NatGatewayAddresses'][0]['AllocationId']
            )
        except:
            pass

    # создание EIP и NAT
    eip = natClient.allocate_address(
        Domain=vpcId
    )
    natGateway = natClient.create_nat_gateway(
        AllocationId=eip['AllocationId'],
        SubnetId=subnetId
    )
    response = natClient.describe_nat_gateways(
        Filters=[{
            'Name': 'nat-gateway-id',
            'Values': [natGateway['NatGateway']['NatGatewayId']]
        }]
    )
    while response['NatGateways'][0]['State'] != 'available':
        time.sleep(10)
        response = natClient.describe_nat_gateways(
            Filters=[{
                'Name': 'nat-gateway-id',
                'Values': [natGateway['NatGateway']['NatGatewayId']]
            }]
        )

    # изменение таблиц маршрутизации
    natClient.delete_route(
        DestinationCidrBlock='0.0.0.0/0',
        RouteTableId=routetableId
    )
    response = natClient.create_route(
        DestinationCidrBlock='0.0.0.0/0',
        NatGatewayId=natGateway['NatGateway']['NatGatewayId'],
        RouteTableId=routetableId
    )

    # сброс функций лямбда
    response = lambdaClient.put_function_concurrency(
        FunctionName='feiScraperEvent--dev',
        ReservedConcurrentExecutions=1
    )
    response = lambdaClient.put_function_concurrency(
        FunctionName='feiScraperContest--dev',
        ReservedConcurrentExecutions=1
    )
    response = lambdaClient.put_function_concurrency(
        FunctionName='feiScraperResult--dev',
        ReservedConcurrentExecutions=1
    )

Объяснение:

Идея заключается в использовании возможности AWS Lambda работать внутри VPC в нашу пользу. Мы используем NAT-шлюз для связи с интернетом, и каждый раз, когда мы обнаруживаем, что наш парсер заблокирован, мы удаляем текущий NAT-шлюз и создаем новый. Если вы не знаете, как использовать NAT-шлюз с Lambda, прочитайте следующую статью:

AWS Lambda функции с статическим IP-адресом

Внутри Compare52 мы создаем много серверных микросервисов на AWS Lambda, что отлично подходит для запуска безсостоятельных...

medium.com

Как видно в приведенном выше коде, я использую три различные функции Lambda для парсинга данных. Одна из них управляет веб-запросами и вызывает функцию смены IP-адреса, как только она обнаруживает, что мы заблокированы.

Итак, первое, что мы делаем после вызова этой функции, - это ограничиваем скорость всех функций парсинга, чтобы они не могли быть вызваны во время сброса NAT-шлюза. Затем мы просто удаляем текущий NAT-шлюз и его назначенный статический IP-адрес и создаем новый. Наконец, мы опрашиваем метод natClient.describe_nat_gateway, чтобы проверить, был ли создан шлюз, и как только он будет создан, мы настраиваем таблицы маршрутизации используемой VPC.

Заключение:

Несмотря на то, что этот метод немного примитивен, он является эффективным способом избежать постоянной блокировки ботами-сканерами.

Также не забудьте установить тайм-аут функции более чем в одну минуту и тридцать секунд, иначе она завершится по тайм-ауту.