Рубрики
Без рубрики

Пока Bye 403: Строительство фильтровая Устойчива веб-Гусеника Часть II: Создание списка прокси

Создание списка прокси для почти безграничной подачи одноразовых IP-адресов!. Теги с Python, наукой данных, обсуждение, учиться в коде.

Первоначально опубликовано в блоге кодирования утки: www.ccstechme.com/coding-duck-blog

Woohooo! У нас есть наша среда, настроенная и готова начать строить наш бот! Видеть в качестве последнего поста в этой серии (Расположенный здесь) был в основном информационным, давайте направимся прямо в код для двух.

Итак, мое предположение, что если вы читаете эту серию до сих пор, что вы знаете основы веб-соскабливания в Python, и что вы хотите узнать, как не заблокировать, а не основы. Так что давайте поправляемся в первую линию защиты, которую мы имеем против веб-фильтров: IP-адрес Cycling

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

Существуют бесплатные варианты, но невыгодное положение существует, что эти списки IP-адресов обычно контролируются и длится только пару часов, прежде чем они заблокированы. Но есть несколько хороших новостей: бесплатные провайдеры прокси (хорошие в любом случае) возникают новые IPS быстрее, чем их старые. Так что мы собираемся использовать мой личный любимый: free-proxy-list.net

Чтобы эффективно использовать это и принять участие в IPS, которые мы использовали и заброшены, мы собираемся построить веб-скребок, чтобы динамически извлечь IPS! Первый шаг в этом процессе и теме этой статьи будет создавать наш список прокси. Первый шаг – создать новый файл, называемый Proxy_retriever.py, который содержит следующее:

import requests
import pandas as pd

from bs4 import BeautifulSoup

class proxyRetriever():

    def __init__(self):
        self.s = requests.Session()
        self.ip_list = []

До настоящего времени до сих пор. Мы импортировали нашу HTTP-библиотеку (запросы) и наш HTML Parser (BeautifulSoup), а также библиотека, которую мы собираемся использовать для создания файла CSV, содержащего наши прокси (Pandas). Далее мы создаем новый класс, называемый Proxyretreverver для обработки всех действий, участвующих в создании нашего списка. Теперь вы можете по-разному выложить свой проект, насколько вы используете концепции OOP. Но, по моему личному мнению, я чувствую, что приложение, которое так же разделено, насколько это возможно, облегчает жизнь для себя и всех, кто использует ваш код. В основном, каждый класс обрабатывает одну общую задачу (например, создание списка прокси). Каждая функция в этом классе будет обрабатывать одну конкретную задачу, чем более конкретнее, тем лучше. Таким образом, ваш код будет очень сухим, и отладка будет CINCH, потому что, если что-то не работает правильно, у вас будет очень хорошее представление о том, где проблема основана исключительно на каком классе и функции, чтобы обращаться с этим, Очень конкретная вещь.

Вы также заметите, что мы определяем здесь сеанс запросов, а не просто запроса. Для этого есть несколько причин, что я нахожу верхнее, чем несколько раз, используя односторонние HTTP-запросы, но специальный пост на который скоро придет Так что я не пойду в это здесь. Просто играйте вместе на данный момент.

Второй свойство классов – это IP_List, мы будем строить. Определение наших свойств таким образом, просто упрощает наши классные функции для обмена доступом к этой конкретной переменной, без необходимости передавать данные друг к другу, которые могут а) получить грязную, когда несколько потоков и/или процессы становятся вовлечены, а б) даже в однопоточной среде. Для меня это не имеет значения, насколько элегантным вашим решением является или насколько он заставляет вас выглядеть, если человек, который поддерживает его, когда у вас больше нет, не имеет никакого ключа, как с ним работать. Делаясь выглядеть более умным, чем следующий парень, является та разнообцвечение типа, которое не имеет места в окружающей среде как совместное и разнообразное, как развитие и инженерное поле. Простые, читаемые, легко следующие решения превосходят те, которые могут быть мелочи быстрее или более эффективными, но совершенно несостоятельны.

Теперь, когда наш класс определяется и имеет некоторое поведение инициализации, давайте добавим нашу первую функцию:

def connect_and_parse(self, website):
        r = self.s.get(website)
        soup = BeautifulSoup(r.text, "html.parser")
        proxy_table = soup.find('tbody')
        proxy_list = proxy_table.find_all('tr')
        elites = [tr for tr in proxy_list if 'elite' in tr.text]
        tds = []
        for tr in elites:
            tds.append([td.text for td in tr])   
        return tds

С принципом «одной функции на функцию» Connect_and_Parse принимает веб-адрес в качестве аргумента (в данном случае ‘ https://free-proxy-list.net/’ ), подключается через наши запросы и вытаскивает HTML, расположенный по этому адресу. Ради простоты, я склонен использовать анализатор «HTML.Parser», включенный в BuestionSoup, а не полагаться на другую зависимость, такую как LXML.

Pro Tip: помните, BeautifulSououp – разметки парсера. Он работает с HTML-струнами и ничего другого. Я вижу, что многие люди попадают в канавку и передают объект отклика (в этом случае R) для красивой конструкции и достигли исключения. Наш ответ – это объект, который содержит свойства, с которыми работает красивая конструкция (например, .Text и .Content), но бесполезно нам сама по себе. Просто не забудьте пройти r.text или r.content, чтобы избежать этого раздражающего задержки.

Использование инструментов браузера ваших предпочтений (я использую инструменты Chrome Dev), изучите содержимое сайта, чтобы найти, что таблица, содержащая нашу информацию прокси, является первым экземпляром класса HTML. Вызов функции sout.find () Возвращает первый вхождение этого класса и назначает его переменной Proxy_Table.

Чтобы создать список строк этой таблицы, назначьте Proxy_Table.find_all («TR») в переменную Proxy_List.

Pro Tip: Любой элемент, возвращенный функцией SOUS.FIND (), будет объектом BeautifulSoup, который вы можете дополнительно разобраться с Find (), find_all (), next_sibry () и т. Д. Тем не менее, SUP.FIND_ALL () возвращает список, заполненный объектами BeautifulSoup. Даже если этот список содержит только один элемент, вам все равно нужно получить доступ к нему конкретно, чтобы разбирать его дальше. В этом примере, Если бы мы попытались назвать что-то вроде proxy_list.find («какой-то другой элемент») , мы получим исключение, потому что переменная Proxy_List представляет собой список, содержащий объекты супа, а не сам объект супа. Чтобы дополнительно разобрать элемент find_all (), итерации через список или доступа к элементу по его индексу.

Наша следующая строка создает список «элитных» прокси состояния. Эти типы прокси являются полностью анонимными и очень сложными для фильтров для удаления и фильтрации на лету. Они также используют HTTPS, чтобы ваш трафик будет как анонимным и зашифрован SSL, обе вещи, которые мы хотим, чтобы наш гусеник имел. Этот процесс выполнен с использованием понимания списка, который вы можете получить курс сбоя здесь здесь

Следующая строка является примером читаемости против умышленности. Мы создаем список ячеек в каждой строке, хранящейся в списке элит. Это можно сделать со списком пониманием, однако это было бы вложенным списком пониманием, которое было бы немного тизер мозга, сложно прочитать, и нужно будет читать несколько раз, чтобы понять логический поток. Это сделало бы отладки любых вопросов, которые они могли бы позже развивать, займет гораздо дольше, чем необходимо. Таким образом, вместо этого мы используем традиционную петлю для доступа к строкам в элитных elites, а затем используйте более простой, более читаемый список списка для обработки ячеек каждой строки в нашу желаемую информацию о каждом прокси, который мы собираем.

Прохладный! Таким образом, мы получили информацию о прокси в аккуратном маленьком списке списков. Теперь, чтобы обработать его и бросить его в файл CSV, мы можем ссылаться позже:

def clean_and_sort(self, data_set):
        columns = ['Address', 'Port', 'Country_Code', 'Country', 'Proxy_Type']
        mapped_lists = {}
        i=0
        while i < 5:
            mapped_lists.update({columns[i]: [tag[i] for tag in tags_stripped_data]})
            i+=1
        df = pd.DataFrame(mapped_lists, columns=columns)
        df.to_csv('proxy_ips.csv')

Эта следующая функция принимает вывод нашей предыдущей функции (наша коллекция списков деталей прокси), очищает ее, сортирует ее и выводит его к CSV. Переменная столбцов – это список, содержащий имена столбцов, которые мы будем использовать для нашего файла CSV. Затем мы создаем пустой словарь (maphe_lists) и используете цикл While, чтобы обработать только первые 5 элементов в каждом списке, который мы создали в нашей функции Connect_And_Parse. Это необходимо, потому что, если мы повторно проверим Free-Proxy-list.net, таблица содержит 8 столбцов в строке. Мы заботимся только о первых 5. Теперь мы могли бы написать наш скребок, чтобы получить только первые 5. Тем не менее, Connect_And_Parse не несет ответственности за уборку и сортировку наших данных, только схватив его и возвращая его как бесцеремонный BLOB. Это самое эффективное решение? Возможно, возможно нет. Но когда дело доходит до отладки проблемы с сортировкой данных правильно после получения, вы будете рады, что вы пошли об этом таким образом. Потому что независимо от того, что вы меняете (и потенциально ломаются) в процессе отладки функции Clean_And_sort, Connect_and_Parse все равно будет работать нормально. Можете ли вы сказать то же самое, если оба обязательства были переданы в Connect_And_Parse в одиночку?

Оттуда мы призываем Pands, чтобы создать dataframe из данных в наших словаре maped_lists, используя наш список столбцов в качестве заголовков столбцов, а также экспортируя dataframe в наш новый файл, proxy_ips.csv. После открытия содержимое будет выглядеть так:

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

Оригинал: “https://dev.to/kaelscion/bye-bye-403-building-a-filter-resistant-web-crawler-part-ii-building-a-proxy-list-4fi9”