Невозможно использовать разные прокси для выполнения последующих запросов - PullRequest
0 голосов
/ 11 января 2019

Я написал скрипт на python, использующий прокси для очистки ссылок разных постов, проходящих через разные страницы. My goal here is to make two subsequesnt requests using different proxies from a list.

Сценарий берет случайные прокси из списка и отправляет запрос с помощью функции make_requests(), а затем снова делает другой запрос, выбирая другого прокси из списка, используя недавно заполненные ссылки с помощью функции make_ano_requests().

Наконец, get_title() функция печатает результат.

Однако, если какой-либо прокси не работает, его исключают из списка с помощью одной из двух функций make_requests() или make_ano_requests().

Когда я запускаю сценарий, он, кажется, работает, но где-то в процессе его выполнения сценарий застревает и никогда не пытается выполнить задачу. Как я могу выполнить задачу?

Это то, что я написал до сих пор ( proxyVault содержит здесь поддельные прокси):

import random
import requests
from random import choice
from bs4 import BeautifulSoup
from urllib.parse import urljoin

base_url = 'https://stackoverflow.com/questions/tagged/web-scraping'
lead_urls = [f'https://stackoverflow.com/questions/tagged/web-scraping?sort='
            f'newest&page={page}&pagesize=50' for page in range(1, 5)]

linkList = []

proxyVault = ['103.110.37.244:36022', '180.254.218.229:8080', '110.74.197.207:50632', '1.20.101.95:49001', '200.10.193.90:8080', '173.164.26.117:3128', '103.228.118.66:43002', '178.128.231.201:3128', '1.2.169.54:55312', '181.52.85.249:31487', '97.64.135.4:8080', '190.96.214.123:53251', '52.144.107.142:31923', '45.5.224.145:52035', '89.218.22.178:8080', '192.241.143.186:80', '113.53.29.218:38310', '36.78.131.182:39243']

def make_requests(url):
    proxy_url = choice(proxyVault)
    proxy = {'https': f'http://{proxy_url}'}
    try:
        res = requests.get(url, proxies=proxy)
        soup = BeautifulSoup(res.text, "lxml")
        linkList.extend([urljoin(base_url, item.get("href")) for item in soup.select(".summary .question-hyperlink")])
    except requests.exceptions.ProxyError:
        if proxy_url in proxyVault:
            proxyVault.remove(proxy_url)
            print(f'kicked out bad proxy by first func: {proxy_url}')
        return make_requests(url)

def make_ano_requests(url):
    proxy_url = choice(proxyVault)
    proxy = {'https': f'http://{proxy_url}'}
    try:
        res = requests.get(url, proxies=proxy)
        get_title(res.text)
    except requests.exceptions.ProxyError:
        if proxy_url in proxyVault:
            proxyVault.remove(proxy_url)
            print(f'kicked out bad proxy by second func: {proxy_url}')
        return make_ano_requests(url)

def get_title(response):
    soup = BeautifulSoup(response, "lxml")
    print(soup.select_one("h1[itemprop='name'] a").text)

if __name__ == '__main__':
    for lead_url in lead_urls:
        make_requests(lead_url)

    for single_link in linkList:
        make_ano_requests(single_link)

Ответы [ 2 ]

0 голосов
/ 20 января 2019

Вы можете ускорить процесс фильтрации прокси, используя asyncio и aiohttp. Примерно так:

import aiohttp
import asyncio
import random
import requests
from random import choice
from bs4 import BeautifulSoup
from urllib.parse import urljoin


base_url = 'https://stackoverflow.com/questions/tagged/web-scraping'
lead_urls = [f'https://stackoverflow.com/questions/tagged/web-scraping?sort=' \
             f'newest&page={page}&pagesize=50' for page in range(1, 5)]
linkList = []

proxyVault = ['103.110.37.244:36022', '180.254.218.229:8080', '110.74.197.207:50632', '1.20.101.95:49001',
              '200.10.193.90:8080', '173.164.26.117:3128', '103.228.118.66:43002', '178.128.231.201:3128',
              '1.2.169.54:55312', '181.52.85.249:31487', '97.64.135.4:8080', '190.96.214.123:53251',
              '52.144.107.142:31923', '45.5.224.145:52035', '89.218.22.178:8080', '192.241.143.186:80',
              '113.53.29.218:38310', '36.78.131.182:39243']

def make_ano_requests(url):
    proxy_url = choice(proxyVault)
    proxy = {'https': f'http://{proxy_url}'}
    try:
        res = requests.get(url, proxies=proxy, timeout=5)
        get_title(res.text)
    except requests.exceptions.ProxyError:
        if proxy_url in proxyVault:
            proxyVault.remove(proxy_url)
            print(f'kicked out bad proxy by second func: {proxy_url}')
        return make_ano_requests(url)


def get_title(response):
    soup = BeautifulSoup(response, "lxml")
    print(soup.select_one("h1[itemprop='name'] a").text)


async def fetch(session, url, proxy_url):
    proxy = f'http://{proxy_url}'

    try:
        async with session.get(url, proxy=proxy) as response:
            return await response.text()
    except aiohttp.client_exceptions.ClientProxyConnectionError:
        print(f'kicked out bad proxy by first func: {proxy_url}')
        proxyVault.remove(proxy_url)


async def make_requests():
    tasks = []
    async with aiohttp.ClientSession() as session:
        for proxy in proxyVault:
            tasks.append(fetch(session, base_url, proxy))

        responses = await asyncio.gather(*tasks)

        print(f'Usefull proxies: {proxyVault}')
        for res in responses:
            if res:
                soup = BeautifulSoup(res.text, "lxml")
                linkList.extend(
                    [urljoin(base_url, item.get("href")) for item in soup.select(".summary .question-hyperlink")])


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(make_requests())

    for single_link in linkList:
        make_ano_requests(single_link)
0 голосов
/ 11 января 2019

Вполне возможно, что ваши requests.get заставляют его "зависать", потому что у них нет тайм-аутов. Как документация говорит:

Практически весь производственный код должен использовать этот параметр почти во всех Запросы. Невыполнение этого требования может привести к зависанию вашей программы на неопределенный срок

Поэтому я предлагаю изменить его на res = requests.get(url, proxies=proxy, timeout=1), чтобы он не зависал.

Это, однако, действительно неопрятно. Чтобы ускорить его, я бы предложил удалить второй запрос и вместо того, чтобы получать ссылки из запросов 1, получая строки [item.string for item in soup.select(".summary .question-hyperlink")], которые чаще всего совпадают с заголовками.

Редактировать, добавлен код для перехвата тайм-аутов в request.get:

import random
import requests
from random import choice
from bs4 import BeautifulSoup
from urllib.parse import urljoin
import urllib3

base_url = 'https://stackoverflow.com/questions/tagged/web-scraping'
lead_urls = [f'https://stackoverflow.com/questions/tagged/web-scraping?sort='
            f'newest&page={page}&pagesize=50' for page in range(1, 5)]

linkList = []

proxyVault = ['103.110.37.244:36022', '180.254.218.229:8080', '110.74.197.207:50632', '1.20.101.95:49001', '200.10.193.90:8080', '173.164.26.117:3128', '103.228.118.66:43002', '178.128.231.201:3128', '1.2.169.54:55312', '181.52.85.249:31487', '97.64.135.4:8080', '190.96.214.123:53251', '52.144.107.142:31923', '45.5.224.145:52035', '89.218.22.178:8080', '192.241.143.186:80', '113.53.29.218:38310', '36.78.131.182:39243']

def make_requests(url):
    proxy_url = choice(proxyVault)
    proxy = {'https': f'http://{proxy_url}'}
    try:
        res = requests.get(url, proxies=proxy, timeout=1)
        soup = BeautifulSoup(res.text, "lxml")
        linkList.extend([urljoin(base_url, item.get("href")) for item in soup.select(".summary .question-hyperlink")])
    except (requests.exceptions.ProxyError,
            requests.exceptions.Timeout,
            requests.exceptions.ConnectionError,
            urllib3.exceptions.MaxRetryError):
        if proxy_url in proxyVault:
            proxyVault.remove(proxy_url)
            print(f'kicked out bad proxy by first func: {proxy_url}')
        return make_requests(url)

def make_ano_requests(url):
    proxy_url = choice(proxyVault)
    proxy = {'https': f'http://{proxy_url}'}
    try:
        res = requests.get(url, proxies=proxy, timeout=1)
        get_title(res.text)
    except (requests.exceptions.ProxyError,
            requests.exceptions.Timeout,
            requests.exceptions.ConnectionError,
            urllib3.exceptions.MaxRetryError):
        if proxy_url in proxyVault:
            proxyVault.remove(proxy_url)
            print(f'kicked out bad proxy by second func: {proxy_url}')
        return make_ano_requests(url)

def get_title(response):
    soup = BeautifulSoup(response, "lxml")
    print(soup.select_one("h1[itemprop='name'] a").text)

if __name__ == '__main__':
    for lead_url in lead_urls:
        make_requests(lead_url)

    for single_link in linkList:
        make_ano_requests(single_link)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...