Непрерывное исследование нескольких ULR с меньшим количеством потоков, как управлять потоками

1

Фон:

Я хочу отслеживать 100 URL-адресов (сделайте снимок и сохраните его, если контент отличается от предыдущего), мой план заключается в использовании urllib.request для сканирования их каждые x минут, скажем x = 5, без остановок.

Поэтому я не могу использовать сингл для цикла и сна, так как я хочу начать обнаружение для ULR1, а затем начать URL2 почти одновременно.

while TRUE:
  for url in urlList:
    do_detection()
    time.sleep(sleepLength)

Поэтому я должен использовать пул? Но я должен ограничить поток небольшим количеством, которое может обрабатывать мой процессор (не может установить 100 потоков, если у меня есть 100 ULR)

Мой вопрос:

Даже я могу отправить 100 URL-адресов в свой список в ThreadPool (4) с четырьмя потоками, как я должен конструировать для управления каждым потоком для обработки URL-адреса 100/4 = 25, поэтому нитки исследуют URL1, sleep (300) перед следующим зондом к URL1, а затем сделать URL2.... ULR25 и вернуться к URL1...? Я не хочу ждать 5 минут * 25 для полного цикла.

Код Psuedo или примеры будут большой помощью! Я не могу найти или подумать, как заставить looper() и детектор() вести себя по мере необходимости?

(Я думаю, что как отказаться от нескольких html-страниц параллельно с beautifulsoup в python? Это близкий, но не точный ответ)

Может быть, что-то вроде этого для каждого потока? Я попытаюсь разобраться, как разбить 100 элементов на каждый поток. using pool.map(func, iterable [, chunksize]) принимает список, и я могу установить chunksize на 25.

def one_thread(Url):

    For url in Url[0:24]:
          CurrentDetect(url)
    if 300-timelapsed>0:
        remain_sleeping=300-timtlapsed
    else:
        remain_sleeping=0


    sleep (remain_sleeping)

    For url in Url[0:24]:
          NextDetect()

Нерабочий код, который я пытаюсь написать:

import urllib.request as req
import time
def url_reader(url = "http://stackoverflow.com"):

    try
        f = req.urlopen(url)
        print (f.read())

    except Exception as err
        print (err)

def save_state():
    pass
    return []

def looper (sleepLength=720,urlList):
    for url in urlList: #initial save
        Latest_saved.append(save_state(url_reader(url))) # return a list
    while TRUE:
        pool = ThreadPool(4) 


        results = pool.map(urllib2.urlopen, urls)
        time.sleep(sleepLength)  # how to parallel this? if we have 100 urls, then takes 100*20 min to loop?
        detector(urlList) #? use last saved status returned to compare?

def detector (urlList):




    for url in urlList:
            contentFirst=url_reader(url)

            contentNext=url_reader(url)

            if contentFirst!=contentNext:
                save_state(contentFirst)
                save_state(contentNext)
  • 1
    Есть предложение использовать scrapy, который имеет встроенное распределение потоков?
  • 0
    Взгляните на 17.4.2.1. ThreadPoolExecutor Пример .
Показать ещё 1 комментарий
Теги:
multithreading

1 ответ

0
Лучший ответ

Вам необходимо установить запросы,

pip install requests

если вы хотите использовать следующий код:

# -*- coding: utf-8 -*-

import concurrent.futures
import requests
import queue
import threading

# URL Pool
URLS = [
    # Put your urls here
]

# Time interval (in seconds)
INTERVAL = 5 * 60

# The number of worker threads
MAX_WORKERS = 4

# You should set up request headers
# if you want to better evade anti-spider programs
HEADERS = {
    'Accept': '*/*',
    'Accept-Encoding': 'gzip, deflate',
    'Accept-Language': 'en-US,en;q=0.9',
    'Cache-Control': 'max-age=0',
    'Connection': 'keep-alive',
    #'Host': None,
    'If-Modified-Since': '0',
    #'Referer': None,
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36',
}

############################

def handle_response(response):
    # TODO implement your logics here !!!
    raise RuntimeError('Please implement function 'handle_response'!')

# Retrieve a single page and report the URL and contents
def load_url(session, url):
    #print('load_url(session, url={})'.format(url))
    response = session.get(url)
    if response.status_code == 200:
        # You can refactor this part and
        # make it run in another thread
        # devoted to handling local IO tasks,
        # to reduce the burden of Net IO worker threads
        return handle_response(response)

def ThreadPoolExecutor():
    return concurrent.futures.ThreadPoolExecutor(max_workers=MAX_WORKERS)

# Generate a session object
def Session():
    session = requests.Session()
    session.headers.update(HEADERS)
    return session

# We can use a with statement to ensure threads are cleaned up promptly
with ThreadPoolExecutor() as executor, Session() as session:
    if not URLS:
        raise RuntimeError('Please fill in the array 'URLS' to start probing!')

    tasks = queue.Queue()

    for url in URLS:
        tasks.put_nowait(url)

    def wind_up(url):
        #print('wind_up(url={})'.format(url))
        tasks.put(url)

    while True:
        url = tasks.get()

        # Work
        executor.submit(load_url, session, url)

        threading.Timer(interval=INTERVAL, function=wind_up, args=(url,)).start()
  • 0
    Большое спасибо KaiserKatze! Я попробовал код, и он застрял в load_url (), не заканчивая session.get (url). Я сделаю некоторую отладку, возможно, сняв некоторую блокировку или протестировав более простое действие, чем чтение URL, потому что я вижу, как запускаются первые 2 рабочих, но сразу же отправляются и другие URL, возможно, блокировка очереди или что-то еще?
  • 0
    Скорее всего, 1 объект сеанса не может быть использован двумя потоками одновременно?
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню