May 13, 2019

Парсинг сайта с прокси на Python 3 + BS4

Начнём с зависимостей.

import requests
from bs4 import BeautifulSoup

Установка BeautifulSoup была в прошлом уроке, так что объяснять повторно не буду. Грабить прокси мы будем с этого сайта: http://foxtools.ru/Proxy

Прокси расположены в таблицах (td), а точнее в 2х таблицах с разными стилями, отсюда и небольшой костыль. Код я обернул в функцию которая возвращает массив с прокси вида: "192.168.4.4:8080". И так, ниже я кину полную функцию и после буду объяснять что да как.

def proxy_grab():
	proxy = []
	for m in range(int(soup.find_all("div", {"class": "pager"})[-1].find_all("a")[-1].contents[0]) + 1):
		rer = requests.get("http://foxtools.ru/Proxy?page=" + str(m))
		soup2 = BeautifulSoup(rer.text, 'html.parser')
		for i in range(len(soup2.find_all('tr', {"class": "alt"}))):
			table = soup2.find_all('tr', {"class": "alt"})[i]
			ip = table.find_all('td')[1].contents[0]
			port = table.find_all('td')[2].contents[0]
			table2 = soup2.find_all('tr', {"class": ""})[i + 1]
			ip2 = table2.find_all('td')[1].contents[0]
			port2 = table2.find_all('td')[2].contents[0]
			proxy.append(str(ip) + ":" + str(port))
			proxy.append(str(ip2) + ":" + str(port2))
	return proxy

Для начала нам надо узнать сколько есть страниц на сайте. У нас 6 страниц, полный список страниц предоставлен в элементе :

soup.find_all("div", {"class": "pager"})[-1].find_all("a")[-1].contents[0]

Отсюда мы получаем число страниц. Оно будет как строка, поэтому мы преобразуем его в int и прибавим 1 ибо цикл будет идти до 5 потому что начинается с 0, но добавив единицу мы получим цикл до последней - 6 страницы.

Далее, в цикле мы переходим на страницу, например один, далее создаём объект супа с этой страницей, и уже в длине массива со всеми таблицами вытаскиваем с таблиц айпи и порт. У нас 2 класса таблиц, одна с пустым классом, другая с классом alt : soup2.find_all('tr', {"class": "alt"}) , soup2.find_all('tr', {"class": ""}).

Как можно заметить у второй таблицы "table2" в конце есть приписка [i + 1] это потому что нулевая таблица у нас это не таблица с ip и port, это название таблиц, сейчас покажу в скрине.

Вот это нулевой элемент, поэтому мы прибавляем к нему единицу что бы получать айпи и порт. Если же вам не надо добавлять всех в массив и вы хотите видеть просто вывод то ниже будет код который будет выдавать инфу по айпи, порту, страна, скорость, тип прокси и когда был прочекан.

for m in range(int(soup.find_all("div", {"class": "pager"})[-1].find_all("a")[-1].contents[0]) + 1):
	rer = requests.get("http://foxtools.ru/Proxy?page=" + str(m))
	soup2 = BeautifulSoup(rer.text, 'html.parser')
	for i in range(len(soup2.find_all('tr', {"class": "alt"}))):
		table = soup2.find_all('tr', {"class": "alt"})[i]
		ip = table.find_all('td')[1].contents[0]
		port = table.find_all('td')[2].contents[0]
		country = table.find_all('td')[3].contents[-1]
		speed = table.find_all('td')[4].contents[-1]
		type_proxy = table.find_all('td')[5].contents[-1]
		status_check = table.find_all('td')[7].contents[-1]
		print("Айпи: " + ip + "\n" + "Порт: " + port + "\n" + "Страна: " + re.sub(r'\s+', ' ', country)[1:] + '\n' + "Скорость: " + re.sub(r'\s+', ' ', speed)[1:] + '\n' + "Тип прокси: " + re.sub(r'\s+', ' ', type_proxy)[1:] + '\n' + "Время проверки: " + status_check + '\n' + "________________________________________")
		table2 = soup2.find_all('tr', {"class": ""})[i + 1]
		ip2 = table2.find_all('td')[1].contents[0]
		port2 = table2.find_all('td')[2].contents[0]
		country2 = table2.find_all('td')[3].contents[-1]
		speed2 = table2.find_all('td')[4].contents[-1]
		type_proxy2 = table2.find_all('td')[5].contents[-1]
		status_check2 = table2.find_all('td')[7].contents[-1]
		print("Айпи: " + ip2 + "\n" + "Порт: " + port2 + "\n" + "Страна: " + re.sub(r'\s+', ' ', country2)[1:] + '\n' + "Скорость: " + re.sub(r'\s+', ' ', speed2)[1:] + '\n' + "Тип прокси: " + re.sub(r'\s+', ' ', type_proxy2)[1:] + '\n' + "Время проверки: " + status_check2 + '\n' + "_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_")

Вот это выдаст вам в вашу консоль всё необходимое. Скрин ниже:

Теперь же нам надо прочекать прокси, у меня это вышло не очень хорошо и вообще не советую использовать этот код. Вышло вот так:

def proxy_check(proxy_list):
	f = open("proxy_good.txt", "a")
	for proxy in proxy_list:
		try:
			rwww = requests.get("http://myip.ru", timeout=2, proxies={"http": proxy})
			if rwww.status_code == 200:
				print("[+] " + proxy + " [+]")
				f.write(proxy + '\n')
			else:
				pass
		except:
			print("[-][-][-][-] " + proxy + " [-][-][-][-]")

Мы создали функцию которая принимает в себя массив с прокси вида "192.168.4.4:8080" то есть айпи:порт. С помощью цикла мы пробуем подключиться к каждому прокси с таймаутом в 2 секунды. Таймаут можете подбирать по своему усмотрению. Из 160 прокси гудов было 20, но это при таймауте в 2 секунды. Так же все гуд прокси записываются в файл и выводятся в консоль.

Вызывать функцию мы может вот так:

proxy_check(proxy_grab())

А теперь подарочек. Есть репозиторий который грабит прокси : https://github.com/constverum/ProxyBroker

И я немного посмотрев примеры успешно позаимствовал немного примеров. И так, мы имеем:

import asyncio
from proxybroker import Broker


async def show(proxies):
    f = open("test_proxy.txt", 'a')
    while True:
        proxy = await proxies.get()
        if proxy is None: break
        proto = 'https' if 'HTTPS' in proxy.types else 'http'
        f.write(proxy.host + ":" + str(proxy.port) + "\n")


proxies = asyncio.Queue()
broker = Broker(proxies)
tasks = asyncio.gather(
    broker.find(types=['HTTP', 'HTTPS']),
    show(proxies))


loop = asyncio.get_event_loop()
loop.run_until_complete(tasks)

Итак, мы имеем функцию которая записывает в файл гуды "Айпи:Порт"

Вам нужен только репозиторий proxybroker

pip install proxybroker

Далее можете вставить эту функцию в свою IDE или блокнот и запустить, после этого в директории со скриптом создастся текстовый файл в который будут записаны все прокси. Прокси можете чекать с помощью бесплатной утилиты "Elite Proxy Switcher"

https://www.eliteproxyswitcher.com

Ну мне по итогу выбило ошибку после 1500 прокси, но это не важно, мы получили прокси и вот результат чека с помощью софта выше:

А теперь весь листинг программы которая была написана мной. Там результаты не такие радужные как у прокси грабера который был позаимствован с либы ProxyBroker).

def proxy_grab():
	proxy = []
	for m in range(int(soup.find_all("div", {"class": "pager"})[-1].find_all("a")[-1].contents[0]) + 1):
		rer = requests.get("http://foxtools.ru/Proxy?page=" + str(m))
		soup2 = BeautifulSoup(rer.text, 'html.parser')
		for i in range(len(soup2.find_all('tr', {"class": "alt"}))):
			table = soup2.find_all('tr', {"class": "alt"})[i]
			ip = table.find_all('td')[1].contents[0]
			port = table.find_all('td')[2].contents[0]
			table2 = soup2.find_all('tr', {"class": ""})[i + 1]
			ip2 = table2.find_all('td')[1].contents[0]
			port2 = table2.find_all('td')[2].contents[0]
            proxy.append(str(ip) + ":" + str(port))
  			proxy.append(str(ip2) + ":" + str(port2))
  	return proxy
  
  
def proxy_check(proxy_list):
  	f = open("proxy_good.txt", "a")
  	for proxy in proxy_list:
  		try:
  			rwww = requests.get("http://myip.ru", timeout=2, proxies={"http": proxy})
  			if rwww.status_code == 200:
  				print("[+] " + proxy + " [+]")
  				f.write(proxy + '\n')
  			else:
  				pass
  		except:
  			print("[-][-][-][-] " + proxy + " [-][-][-][-]")

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