Как отложить выполнение в ThreadPool? - PullRequest
0 голосов
/ 03 октября 2018

Я написал скрипт на python с использованием multiprocessing.pool.ThreadPool для одновременной обработки нескольких запросов и обеспечения устойчивости процесса очистки.Парсер отлично справляется со своей задачей.

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

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

Это мойсценарий до сих пор:

import requests
from urllib.parse import urljoin
from bs4 import BeautifulSoup
from multiprocessing.pool import ThreadPool

url = "http://srar.com/roster/index.php?agent_search=a"

def get_links(link):
    completelinks = []
    res = requests.get(link)  
    soup = BeautifulSoup(res.text,'lxml')
    for items in soup.select("table.border tr"):
        if not items.select("td a[href^='index.php?agent']"):continue
        data = [urljoin(link,item.get("href")) for item in items.select("td a[href^='index.php?agent']")]
        completelinks.extend(data)
    return completelinks

def get_info(nlink):
    req = requests.get(nlink)
    sauce = BeautifulSoup(req.text,"lxml")
    for tr in sauce.select("table[style$='1px;'] tr")[1:]:
        table = [td.get_text(strip=True) for td in tr.select("td")]
        print(table)

if __name__ == '__main__':
    ThreadPool(20).map(get_info, get_links(url))

Еще раз: все, что мне нужно знать, это правильная позиция в моем сценарии, чтобы поставить задержку.

1 Ответ

0 голосов
/ 03 октября 2018

Для установки задержки между вашими множественными вызовами requests.get(), расположенными в пределах get_info, вам необходимо расширить get_info аргументом задержки, который он может принимать в качестве ввода для вызова time.sleep().Поскольку все ваши рабочие потоки запускаются одновременно, ваши задержки должны быть кумулятивными для каждого вызова.Это означает, что если вы хотите, чтобы ваша задержка между вызовами requests.get() составляла 0,5 секунды, ваш список задержек, которые вы передаете в метод пула, будет выглядеть как [0.0, 0.5, 1.0, 1.5, 2.0, 2.5 ...].

Поскольку нет необходимости изменять get_info, я использую декоратор в приведенном ниже примере для расширения get_info с параметром задержки и вызовом time.sleep(delay).Обратите внимание, что я передаю задержки вместе с другим аргументом для get_info в вызове pool.starmap.

import logging
from multiprocessing.pool import ThreadPool
from functools import wraps

def delayed(func):
    @wraps(func)
    def wrapper(delay, *args, **kwargs):
        time.sleep(delay)  # <--
        return func(*args, **kwargs)
    return wrapper

@delayed
def get_info(nlink):
    info = nlink + '_info'
    logger.info(msg=info)
    return info


def get_links(n):
    return [f'link{i}' for i in range(n)]


def init_logging(level=logging.DEBUG):
    fmt = '[%(asctime)s %(levelname)-8s %(threadName)s' \
          ' %(funcName)s()] --- %(message)s'
    logging.basicConfig(format=fmt, level=level)


if __name__ == '__main__':

    DELAY = 0.5

    init_logging()
    logger = logging.getLogger(__name__)

    links = get_links(10) # ['link0', 'link1', 'link2', ...]
    delays = (x * DELAY for x in range(0, len(links)))
    arguments = zip(delays, links) # (0.0, 'link0'), (0.5, 'link1'), ...

    with ThreadPool(10) as pool:
        result = pool.starmap(get_info, arguments)
        print(result)

Пример вывода:

[2018-10-03 22:04:14,221 INFO     Thread-8 get_info()] --- link0_info
[2018-10-03 22:04:14,721 INFO     Thread-5 get_info()] --- link1_info
[2018-10-03 22:04:15,221 INFO     Thread-3 get_info()] --- link2_info
[2018-10-03 22:04:15,722 INFO     Thread-4 get_info()] --- link3_info
[2018-10-03 22:04:16,223 INFO     Thread-1 get_info()] --- link4_info
[2018-10-03 22:04:16,723 INFO     Thread-6 get_info()] --- link5_info
[2018-10-03 22:04:17,224 INFO     Thread-7 get_info()] --- link6_info
[2018-10-03 22:04:17,723 INFO     Thread-10 get_info()] --- link7_info
[2018-10-03 22:04:18,225 INFO     Thread-9 get_info()] --- link8_info
[2018-10-03 22:04:18,722 INFO     Thread-2 get_info()] --- link9_info
['link0_info', 'link1_info', 'link2_info', 'link3_info', 'link4_info', 
'link5_info', 'link6_info', 'link7_info', 'link8_info', 'link9_info']
...