• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Пишем асинхроннный парсер прокси на python

Peace

(L3) cache
Забанен
Регистрация
19.12.2022
Сообщения
255
Реакции
80
Пожалуйста, обратите внимание, что пользователь заблокирован
Всем привет, хочу поделиться частью кода из всего проекта.
Сегодня разберем https://geonode.com/, там существует бесплатный лист с прокси который мы научимся парсить асинхронно.
Рассмотрите код, там указаны комментарии почти к каждой строчке, а потом приступайте к сбору проекта, пожалуйста!

Приступим:
Python:
async def check_count_pages(session):
    try:
       async with session.get('https://proxylist.geonode.com/api/proxy-list', headers=headers) as response: # запрос на страницу
            data = await response.json() #принимаем информацию сайта в json
            # print(data['total'])
        total = int(data['total']) #Значение количеста прокси переводим в инт
       pages = math.ceil(total / 500) #Теперь, делим количество прокси на 500, т.к 1 json запросе хранится 500 прокси. Таким образом узнаем количество страниц
        pages = int(pages)
        # print(pages)
        return pages #Взращаем
    except Exception as e:
        print(e)
Python:
async def printsecs(session, i, k):
    params = {
        'limit': '500',
        'page': f'{i}',
        'sort_by': 'lastChecked',
        'sort_type': 'desc',
    }
    async with session.get('https://proxylist.geonode.com/api/proxy-list', headers=headers,
                           params=params) as response: #запрос на сайт
        proxies = await response.json() #сохраняем в json

        for proxy in proxies['data']: #шагаем по дате
            if proxy['protocols'][0] == 'socks4': #если протокол равен сокс4
                async with socks4lock: #Блокируем поток для корректной записи
                    async with aiof.open(r'socks4.txt', 'a') as file: #открываем файл для дозаписи
                        await file.write(f"{proxy['ip']}:{proxy['port']}\n") #Записываем прокси
                        await file.flush()
            elif proxy['protocols'][0] == 'socks5': #Все тоже самое что и выше, только другой протокол прокси
                async with socks5lock:
                    async with aiof.open(r'socks5.txt', 'a') as file:
                        await file.write(f"{proxy['ip']}:{proxy['port']}\n")
                        await file.flush()
            elif proxy['protocols'][0] == 'https':
                async with httpslock:
                    async with aiof.open(r'https.txt', 'a') as file:
                        await file.write(f"{proxy['ip']}:{proxy['port']}\n")
                        await file.flush()
            elif proxy['protocols'][0] == 'http':
                async with httplock:
                    async with aiof.open(r'http.txt', 'a') as file:
                        await file.write(f"{proxy['ip']}:{proxy['port']}\n")
                        await file.flush()
        print(f'Обработано страниц с первого сайта - {k}')
Python:
async def main_first_site():
    async with aiohttp.ClientSession() as session:
        tasks = [] # Создаем лист с нашими тасками
        k = 1 # Счетчик для проверки количества отработанных страниц
        pages = await check_count_pages(session) #вызов функции чтобы узнать количество страниц
        for i in range(0, pages): #Шагаем по количеству страниц
            task = asyncio.create_task(printsecs(session, i, k)) #Передаем в нашу основную функцию сессию, страницу и счетчик
            tasks.append(task) #упаковываем таск
            k = k + 1 #счетчик
        await asyncio.gather(*tasks) #распаковываем таски
Python:
import asyncio
import aiohttp
import math
import aiofiles as aiof

socks4lock = asyncio.Lock() # обязательные локи, чтобы запись файла была корректной
socks5lock = asyncio.Lock()
httpslock = asyncio.Lock()
httplock = asyncio.Lock()

headers = {
    'authority': 'proxylist.geonode.com',
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
    'accept-language': 'ru-RU,ru;q=0.9',
    'sec-ch-ua': '"Chromium";v="110", "Not A(Brand";v="24", "Google Chrome";v="110"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-platform': '"Windows"',
    'sec-fetch-dest': 'document',
    'sec-fetch-mode': 'navigate',
    'sec-fetch-site': 'none',
    'sec-fetch-user': '?1',
    'upgrade-insecure-requests': '1',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36',
}


async def printsecs(session, i, k):
    params = {
        'limit': '500',
        'page': f'{i}',
        'sort_by': 'lastChecked',
        'sort_type': 'desc',
    }
    async with session.get('https://proxylist.geonode.com/api/proxy-list', headers=headers,
                           params=params) as response: #запрос на сайт
        proxies = await response.json() #сохраняем в json

        for proxy in proxies['data']: #шагаем по дате
            if proxy['protocols'][0] == 'socks4': #если протокол равен сокс4
                async with socks4lock: #Блокируем поток для корректной записи
                    async with aiof.open(r'socks4.txt', 'a') as file: #открываем файл для дозаписи
                        await file.write(f"{proxy['ip']}:{proxy['port']}\n")
                        await file.flush()
            elif proxy['protocols'][0] == 'socks5':
                async with socks5lock:
                    async with aiof.open(r'socks5.txt', 'a') as file:
                        await file.write(f"{proxy['ip']}:{proxy['port']}\n")
                        await file.flush()
            elif proxy['protocols'][0] == 'https':
                async with httpslock:
                    async with aiof.open(r'https.txt', 'a') as file:
                        await file.write(f"{proxy['ip']}:{proxy['port']}\n")
                        await file.flush()
            elif proxy['protocols'][0] == 'http':
                async with httplock:
                    async with aiof.open(r'http.txt', 'a') as file:
                        await file.write(f"{proxy['ip']}:{proxy['port']}\n")
                        await file.flush()
        print(f'Обработано страниц с первого сайта - {k}')


# async def write_to_file(filename, text):
#     async with aiofiles.open(filename, 'a') as f:
#         await f.write(text)


async def check_count_pages(session):
    try:
       async with session.get('https://proxylist.geonode.com/api/proxy-list', headers=headers) as response: # запрос на страницу
            data = await response.json() #принимаем информацию сайта в json
            # print(data['total'])
        total = int(data['total']) #Значение количеста прокси переводим в инт
       pages = math.ceil(total / 500) #Теперь, делим количество прокси на 500, т.к 1 json запрсе хранится 500 прокси. Таким образом узнаем количество страниц
        pages = int(pages)
        # print(pages)
        return pages #Взращаем
    except Exception as e:
        print(e)


async def main_first_site():
    async with aiohttp.ClientSession() as session:
        tasks = [] # Создаем лист с нашими тасками
        k = 1 # Счетчик для проверки количества отработанных страниц
        pages = await check_count_pages(session) #вызов функции чтобы узнать количество страниц
        for i in range(0, pages): #Шагаем по количеству страниц
            task = asyncio.create_task(printsecs(session, i, k)) #Передаем в нашу основную функцию сессию, страницу и счетчик
            tasks.append(task) #упаковываем таск
            k = k + 1 #счетчик
        await asyncio.gather(*tasks) #распаковываем таски
        return 1

if __name__ == '__main__':
    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
    asyncio.run(main_first_site())
 
Последнее редактирование модератором:
Пожалуйста, обратите внимание, что пользователь заблокирован
Прежде чем делиться знаниями, убедись что они качественные и не вводят в заблуждение читателей.
Конкретно в этом случае ты наговнокодил тривиальную тулзу (подал плохой пример), не выложил код полностью с целью заманить аудиторию в свой всратый канал, и ввел в заблуждение читателей тайтлом "Статья".
Знаете почему большинство форумов считаются школоло? Потому что там полно такого мусора
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Прежде чем делиться знаниями, убедись что они качественные и не вводят в заблуждение читателей.
Конкретно в этом случае ты наговнокодил тривиальную тулзу (подал плохой пример), не выложил код полностью с целью заманить аудиторию в свой всратый канал, и ввел в заблуждение читателей тайтлом "Статья".
Знаете почему большинство форумов считаются школоло? Потому что там полно такого мусора
Ужас столько негатива. Ты ведь был на моем месте и тоже имел мало опыта. Прежде чем так критиковать, нужно предлагать, если я наговногодил, то покажи где во-первых, во-вторых канал не всратый, мне хочется общаться с людьми и делиться наработками, то в чем его всратость ? ЕСЛИ ТЫ ОТКРОЕШЬ ГЛАЗА И ПОСМОТРИШЬ НА МОИ СТАТЬИ, ТО УВИДИШЬ ТРЕД С ПОЛНЫМ ИСХОДНЫМ КОДОМ ЭТОЙ ПРОГРАММЫ. Этот тред создан ради того, чтобы - да набрать пару людей в тг канал(он даже называется ПсевдоКодинг) и чтобы люди корректировали мой код. Печально, что ты тут вкинул столько негатива, написав, что я наговнокодил.
Она может и тривиальная, но дает хороший пример, как парсить в асинхронности. Она пойдет для новичков.
А что это не статья ? Она и вправду может дать какие то знания, которых мне нехватало.
Мне очень печально, что человек столько негатива написать.
 
Последнее редактирование:
Ужас столько негатива. Ты ведь был на моем месте и тоже имел мало опыта. Прежде чем так критиковать, нужно предлагать, если я наговногодил, то покажи где во-первых, во-вторых канал не всратый, мне хочется общаться с людьми и делиться наработками, то в чем его всратость ? ЕСЛИ ТЫ ОТКРОЕШЬ ГЛАЗА И ПОСМОТРИШЬ НА МОИ СТАТЬИ, ТО УВИДИШЬ ТРЕД С ПОЛНЫМ ИСХОДНЫМ КОДОМ ЭТОЙ ПРОГРАММЫ. Этот тред создан ради того, чтобы - да набрать пару людей в тг канал(он даже называется ПсевдоКодинг) и чтобы люди корректировали мой код. Печально, что ты тут вкинул столько негатива, написав, что я наговнокодил, хотя сам в прошлом треде не смог решить простую задачу по асинхронности.
так то это не одобренная реклама паблика, а это не хорошо. При регистрации на форуме предлагается прочитать правила и раздел для новичков.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Конкретно в этом случае ты наговнокодил тривиальную тулзу (подал плохой пример), не выложил код полностью с целью заманить аудиторию в свой всратый канал, и ввел в заблуждение читателей тайтлом "Статья".
Знаете почему большинство форумов считаются школоло? Потому что там полно такого мусора
Всё, понял кто ты такой и как ты общаешься. Пожалуйста, в будущем не заходи на мои треды и не оставляй сообщения, даже реакции. От тебя толкну ноль, ты просто вечно отвечаешь негативно. Ты уже оштрафован 2 раза, печально, что твои сообщения почти всегда состоят из набора неприятных сообщений. Тебе бы проще относиться к вещам и более позитивно отвечать, ведь мы живем жизнь раз и не нужно такой плохой след оставлять.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Я ответил тебе за что дизлайк. Максимально адекватно. Прекрати хныкать и изучи что-нибудь посложнее прежде, чем пытаться учить других своими говеными примерами. Почитай про избыточность, DRY, zen of python в конце-концов.
Ты понял кто я такой, вау. Жаль, но ты не первый выебщик, который мне это говорит. Можешь попробовать залить свою статью на хабр, посмотрим сколько людей считают так же как и я.
Успехов в развитии

upd: зеленка, лолз... ну понятно, как обычно
 
Последнее редактирование:
Пожалуйста, обратите внимание, что пользователь заблокирован
Я ответил тебе за что дизлайк. Максимально адекватно. Прекрати хныкать и изучи что-нибудь посложнее прежде, чем пытаться учить других своими говеными примерами. Почитай про избыточность, DRY, zen of python в конце-концов.
Ты понял кто я такой, вау. Жаль, но ты не первый выебщик, который мне это говорит. Можешь попробовать залить свою статью на хабр, посмотрим сколько людей считают так же как и я.
Успехов в развитии

upd: зеленка, лолз... ну понятно, как обычно
Никто не хныкал, никто даже на хабр не притендует, а просто показать код, но ты даже сейчас не указал, где говно код ? Может покажешь ? Давай без негатива и с большей конкретики, помоги мне пожалуйста. У меня просто пригорело, что такой фидбэк. Просто, видел тебя в прошлом треде и ты хотел помочь. Чисто уже сформировалось мнение о тебе, что ты хороший человек, но когда увидел выше коммент немного скрючило.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Понравилось - Создаем асинхронность.
XD, сори, надо было написать создаем таски) Исправил
 
Сомотри дружище цель статьи это раскрытие какой то темы. Как правило в статьях много ответоветов на вопросы - что, как, почему именно так, какие варианты, почему одни лучше других, какие подводные камни. То есть происходит раскрытие темы. А у тебя просто програмка с коментариями, пример того как можно решить задачу, но это не статья.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Сомотри дружище цель статьи это раскрытие какой то темы. Как правило в статьях много ответоветов на вопросы - что, как, почему именно так, какие варианты, почему одни лучше других, какие подводные камни. То есть происходит раскрытие темы. А у тебя просто програмка с коментариями, пример того как можно решить задачу, но это не статья.
хорошо, попрошу убрать тэг статья
 
Прежде чем так критиковать, нужно предлагать, если я наговногодил, то покажи где
4 лока абсолютно не нужны, достаточно будет одного. Заголовки от accept-language, до юзер-агента тоже не нужны. Названия функций и переменных должны быть читаемы и понятны ( с говорящим названием, для чего создана и что выполняет). Если пишешь код для публичного освещения, не плохо было бы использовать докстринги. Комментировать нужно действительно сложные строчки кода ("Значение количеста прокси переводим в инт", "Шагаем по количеству страниц" - это не информативные комментарии, лол вообще). Запись в файл вынеси в отдельную функцию. Она повторяется 3 РАЗА! ( если ты захочешь изменить алгоритм записи или даже формат файла, придется искать по коду). Урл так же повторяется в коде, и захардкоден, имеет смысл вынести его в глоб переменную.Мб тоже самое стоит сделать с параметрами для запроса. Не увидел обработки ошибок соединения, если сайт будет лежать, или инет упадет, программа крашнется - это плохо. Если не получиться подсчитать количество страниц, будет просто печать ошибки - это не обратботка исключения. Закоментированые фукнции и строки - удали. Если тут асинхроность, гдеколичество потоков на которых работает программа? Так же нет смысла использовать либу math, для обычного деления)
то что ты учишься и хочешь поделиться знаниями с другими это круто) но пока рановато, подучись еще сам)
 
Последнее редактирование:
Пожалуйста, обратите внимание, что пользователь заблокирован
4 лока абсолютно не нужны, достаточно будет одного. Заголовки от accept-language, до юзер-агента тоже не нужны. Названия функций и переменных должны быть читаемы и понятны ( с говорящим названием, для чего создана и что выполняет). Если пишешь код для публичного освещения, не плохо было бы использовать докстринги. Комментировать нужно действительно сложные строчки кода ("Значение количеста прокси переводим в инт", "Шагаем по количеству страниц" - это не информативные комментарии, лол вообще). Запись в файл вынеси в отдельную функцию. Она повторяется 3 РАЗА! ( если ты захочешь изменить алгоритм записи или даже формат файла, придется искать по коду). Урл так же повторяется в коде, и захардкоден, имеет смысл вынести его в глоб переменную.Мб тоже самое стоит сделать с параметрами для запроса. Не увидел обработки ошибок соединения, если сайт будет лежать, или инет упадет, программа крашнется - это плохо. Если не получиться подсчитать количество страниц, будет просто печать ошибки - это не обратботка исключения. Закоментированые фукнции и строки - удали. Если тут асинхроность, гдеколичество потоков на которых работает программа? Так же нет смысла использовать либу math, для обычного деления)
то что ты учишься и хочешь поделиться знаниями с другими это круто) но пока рановато, подучись еще сам)
Спасибо большое! А можете подсказать, как указать количество потоков с которыми должна работать программа? Math использовал для округления к большему. Все остальное уяснил, благодарю !
 
А можете подсказать, как указать количество потоков с которыми должна работать программа?

Тут явно можно улучшить некоторые вещи, но если нужно быстрое решение:

Python:
import asyncio


def main():
    targets = ["apple.com", "google.com"]
    AsyncPool(targets)


class AsyncPool():
    def __init__(self, targets) -> None:
        self.targets = targets
        self.sem = asyncio.BoundedSemaphore(250) # Кол-во задач, выполняющихся параллельно
        loop = asyncio.new_event_loop()
        loop.run_until_complete(self.fabric())

    async def fabric(self):
        tasks = []
        for target in self.targets:
            task = asyncio.ensure_future(self.execute(target))
            tasks.append(task)
        await asyncio.gather(*tasks, return_exceptions=True)

    async def execute(self, target):
        try:
            await self.sem.acquire()
            # Асинхронный таск
            print(target)
        except Exception:
            pass
        finally:
            self.sem.release()

if __name__ == "__main__":
main()
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Тут явно можно улучшить некоторые вещи, но если нужно быстрое решение:

Python:
import asyncio


def main():
    targets = ["apple.com", "google.com"]
    AsyncPool(targets)


class AsyncPool():
    def __init__(self, targets) -> None:
        self.targets = targets
        self.sem = asyncio.BoundedSemaphore(250) # Кол-во задач, выполняющихся параллельно
        loop = asyncio.new_event_loop()
        loop.run_until_complete(self.fabric())

    async def fabric(self):
        tasks = []
        for target in self.targets:
            task = asyncio.ensure_future(self.execute(target))
            tasks.append(task)
        await asyncio.gather(*tasks, return_exceptions=True)

    async def execute(self, target):
        try:
            await self.sem.acquire()
            # Асинхронный таск
            print(target)
        except Exception:
            pass
        finally:
            self.sem.release()

if __name__ == "__main__":
main()
Благодарю !
 
Спасибо большое! А можете подсказать, как указать количество потоков с которыми должна работать программа? Math использовал для округления к большему. Все остальное уяснил, благодарю !
Обычно для контроля потоков создаю воркеров. Ниже кину код как бы я это реализовал. Посмотришь. Будут вопросы отвечу в лс. asyncio и aiohttp на самом деле для такой тривиальной задачи не нужны, тем более на моменте обучения, начни лучше с обычного threading и requests. Будет проще. К слову, я на asyncio и aiohttp не пишу вообще)))


Python:
import asyncio
import aiohttp
from aiohttp import ClientSession


HEADERS = {
    'Authority': 'proxylist.geonode.com',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
    'User-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36',
}
URL_API = 'https://proxylist.geonode.com/api/proxy-list'
FILES_PROXY = {'socks4': 'socks4.txt', 'socks5':'socks5.txt','https':'https.txt', 'http': 'http.txt'}
LIMIT_IN_PAGE = 500
THREADS_COUNT = 3

TOTAL_PROXY = 0
SAVE_PROXY_COUNTER = 0

QUEUE = asyncio.Queue()
THLOCK = asyncio.Lock()


async def write_to_file(filename:str, data:str) -> None:
    async with THLOCK:
        with open(filename, 'a', encoding='UTF-8') as file:
            file.write(f'{data}\n')


async def get_proxys(session: ClientSession, current_page: int):
    params = {'limit': f'{LIMIT_IN_PAGE}', 'page': f'{current_page}', 'sort_by': 'lastChecked', 'sort_type': 'desc'}
    try:
        async with session.get(URL_API, headers=HEADERS, params=params) as response:
            proxies = await response.json()
            return proxies.get('data')
    except Exception as e:
        print(f'[ERR] Fail get proxys in page {current_page} -- {e}')
        return None


async def get_pages_count() -> int:
    global TOTAL_PROXY
    try:
        async with aiohttp.ClientSession() as session:
            async with session.get(URL_API, headers=HEADERS) as response:
                data = await response.json()
    except Exception as e:
        print(f'[ERR] Fail get pages count -- {e}')
        return 0
    TOTAL_PROXY = int(data.get('total', 0))
    return TOTAL_PROXY // LIMIT_IN_PAGE if (TOTAL_PROXY % LIMIT_IN_PAGE) == 0 else TOTAL_PROXY // LIMIT_IN_PAGE + 1


async def worker():
    global QUEUE, SAVE_PROXY_COUNTER
    async with aiohttp.ClientSession() as session:
        while not QUEUE.empty():
            page_num = await QUEUE.get()
            proxys = await get_proxys(session, page_num)
            current_counter = 0
            for proxy in proxys:
                filename = FILES_PROXY[proxy['protocols'][0]]
                line = f"{proxy['ip']}:{proxy['port']}"
                await write_to_file(filename, line)
                current_counter +=1
            SAVE_PROXY_COUNTER += current_counter
            print(f'[+] Page {page_num} saves {current_counter} proxy. Total save: {SAVE_PROXY_COUNTER}')



async def main():
    global TOTAL_PROXY, QUEUE, SAVE_PROXY_COUNTER
    pages = await get_pages_count()
    print(f'[*] Finded proxy {TOTAL_PROXY}, pages {pages}')
    if TOTAL_PROXY == 0:
        exit()
    [QUEUE.put_nowait(page_num) for page_num in range(1, pages+1)]
    threads = [asyncio.create_task(worker()) for _ in range(1, THREADS_COUNT+1)]
    await asyncio.gather(*threads)
    print(f'[*] Finded proxy {TOTAL_PROXY} // Total save {SAVE_PROXY_COUNTER}')

if __name__ == '__main__':
    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
    asyncio.run(main())
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Обычно для контроля потоков создаю воркеров. Ниже кину код как бы я это реализовал. Посмотришь. Будут вопросы отвечу в лс. asyncio и aiohttp на самом деле для такой тривиальной задачи не нужны, тем более на моменте обучения, начни лучше с обычного threading и requests. Будет проще. К слову, я на asyncio и aiohttp не пишу вообще)))


Python:
import asyncio
import aiohttp
from aiohttp import ClientSession


HEADERS = {
    'Authority': 'proxylist.geonode.com',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
    'User-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36',
}
URL_API = 'https://proxylist.geonode.com/api/proxy-list'
FILES_PROXY = {'socks4': 'socks4.txt', 'socks5':'socks5.txt','https':'https.txt', 'http': 'http.txt'}
LIMIT_IN_PAGE = 500
THREADS_COUNT = 3

TOTAL_PROXY = 0
SAVE_PROXY_COUNTER = 0

QUEUE = asyncio.Queue()
THLOCK = asyncio.Lock()


async def write_to_file(filename:str, data:str) -> None:
    async with THLOCK:
        with open(filename, 'a', encoding='UTF-8') as file:
            file.write(f'{data}\n')


async def get_proxys(session: ClientSession, current_page: int):
    params = {'limit': f'{LIMIT_IN_PAGE}', 'page': f'{current_page}', 'sort_by': 'lastChecked', 'sort_type': 'desc'}
    try:
        async with session.get(URL_API, headers=HEADERS, params=params) as response:
            proxies = await response.json()
            return proxies.get('data')
    except Exception as e:
        print(f'[ERR] Fail get proxys in page {current_page} -- {e}')
        return None


async def get_pages_count() -> int:
    global TOTAL_PROXY
    try:
        async with aiohttp.ClientSession() as session:
            async with session.get(URL_API, headers=HEADERS) as response:
                data = await response.json()
    except Exception as e:
        print(f'[ERR] Fail get pages count -- {e}')
        return 0
    TOTAL_PROXY = int(data.get('total', 0))
    return TOTAL_PROXY // LIMIT_IN_PAGE if (TOTAL_PROXY % LIMIT_IN_PAGE) == 0 else TOTAL_PROXY // LIMIT_IN_PAGE + 1


async def worker():
    global QUEUE, SAVE_PROXY_COUNTER
    async with aiohttp.ClientSession() as session:
        while not QUEUE.empty():
            page_num = await QUEUE.get()
            proxys = await get_proxys(session, page_num)
            current_counter = 0
            for proxy in proxys:
                filename = FILES_PROXY[proxy['protocols'][0]]
                line = f"{proxy['ip']}:{proxy['port']}"
                await write_to_file(filename, line)
                current_counter +=1
            SAVE_PROXY_COUNTER += current_counter
            print(f'[+] Page {page_num} saves {current_counter} proxy. Total save: {SAVE_PROXY_COUNTER}')



async def main():
    global TOTAL_PROXY, QUEUE, SAVE_PROXY_COUNTER
    pages = await get_pages_count()
    print(f'[*] Finded proxy {TOTAL_PROXY}, pages {pages}')
    if TOTAL_PROXY == 0:
        exit()
    [QUEUE.put_nowait(page_num) for page_num in range(1, pages+1)]
    threads = [asyncio.create_task(worker()) for _ in range(1, THREADS_COUNT+1)]
    await asyncio.gather(*threads)
    print(f'[*] Finded proxy {TOTAL_PROXY} // Total save {SAVE_PROXY_COUNTER}')

if __name__ == '__main__':
    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
    asyncio.run(main())
Большой вам респект за такую большую помощь ! А почему не используете ? Пишите на threading и requests ?
 
начни лучше с обычного threading и requests
1) Async гараздо более предсказемый
2) Нельзя сказать, что работа с асинхронностью сложнее, чем с потоками
3) Потоки будут менее эффективны в поставленной задаче
4) В python потоки вообщее не являются потоками в прямом смысле этого слова, параллельность для ванильного интерпретатора не доступна, по этой причине так популярна асинронность, она является по сути оптимальной моделью "конкурентности" в условиях наличия GIL.
5) Async позволяет писать гораздо более гибкие проекты, совмещая асинхронные библиотеки. Например, если ты захочешь прикрутить многопоточный чекер к боту, возникнут проблемы, из-за того, что ожидание пула потоков имеет блокировку, следовательно бот перестанет отвечать во время процесса валидации. Да, можно найти обходные пути, но это костыли.

В целом, на мой взгляд, на данный момент нет причин использовать многопоточность, async лучше практически во всех (если не во всех) задачах, которые требуют множества конкурирующих тасков.
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх