Почему мои потоки обработки данных собирают одни идентификаторы много раз, а другие — вообще не собирают?

#python #multithreading #data-mining

#python #многопоточность #интеллектуальный анализ данных

Вопрос:

Я пишу data miner на python с urllib2 и BeautifulSoup для анализа некоторых веб-сайтов, и, пытаясь разделить его процессы на несколько потоков, я получаю следующий результат:

Успешно очищенный идентификатор 301

Успешно очищенный идентификатор 301

Пустой результат с идентификатором 301

«Успешно» означает, что я получил нужные мне данные. «Пусто» означает, что на странице нет того, что мне нужно. «ID» — это целое число, прикрепленное к URL-адресу, например site.com/blog/post /.

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

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

 def constructURLs(settings,idList):
    assert type(settings) is dict
    url = settings['url']
    return [url.replace('<id>',str(ID)) for ID in idList]        

def miner(urls,results):
    for url in urls:
        data = spider.parse(url)
        appendData(data,results)

def mine(settings,results):
    (...)
    urls = constructURLs(settings,idList)
    threads = 3 # number of threads
    urlList = [urls[i::threads] for i in xrange(threads)]
    for urls in urlList:
        t = threading.Thread(target=miner,args=(urls,results))
        t.start()
 

Итак, почему мои потоки анализируют одни и те же результаты много раз, когда все они должны иметь уникальные списки? Почему они возвращают разные результаты, даже с одним и тем же идентификатором? Если вы хотите увидеть больше кода, просто спросите, и я с радостью предоставлю. Спасибо за любую информацию, которую вы можете предоставить!

Комментарии:

1. Является ли ваша функция appendData() потокобезопасной? Если он вызывается повторно из нескольких потоков, все используемые им общие переменные могут быть перезаписаны.

2. Это объяснило бы многие идентификаторы, которые отсутствуют в файле результатов, но инструкции печати об успешном выполнении очистки выполняются перед записью в результаты.

3. На самом деле, проблема потокобезопасности может быть причиной. Ошибка происходит внутри parse(), я это знаю. Функция использует локальную переменную модуля, которую изменяют все экземпляры функции. Вероятно, именно здесь возникает ошибка. Спасибо за ваше понимание!