Основная цель моего скрипта — отфильтровать диапазон чисел (скажем, 5000), числа valid
сохраняются в списке под названием hit_list
. Реальный диапазон, который я просматриваю, намного больше 5000, поэтому мне нужен параллелизм, чтобы сделать время управляемым.
Я не знаю долю допустимых чисел в любом заданном диапазоне, поэтому, когда мой (потоковый) скрипт вернул 9 чисел в hit_list
, я не задавался этим вопросом. Однако в качестве окончательной проверки я запустил скрипт без потоков, как обычный скрипт. Он вернул 214 чисел в hit_list
!
РЕДАКТИРОВАТЬ: Чтобы быть ясным, проблема заключается в том, что числа не находятся правильно, а не сохраняются правильно.
Мне очень щедро помогли с созданием этой программы, как на SO, здесь и Reddit, здесь.
Ниже приведен скрипт с потоками. Я подозреваю, что проблема связана с блокировкой (хотя у меня сложилось впечатление, что concurrent.futures решила эту проблему автоматически) или, возможно, с количеством рабочих/чанков. Но, как я уверен, вы уже можете сказать, я новичок, так что это может быть что угодно!
import concurrent.futures as cf
import requests
from bs4 import BeautifulSoup
import time
from datetime import datetime
import xlwt
hit_list =[]
print('-List Created')
startrange= 100000000
end_range = 100005000
startTime = datetime.now()
print(datetime.now())
url = 'https://ndber.seai.ie/pass/ber/search.aspx'
#print('Working...')
def id_filter(_range):
with requests.session() as s:
s.headers.update({
'user-agent': 'For more information on this data collection please contact #########'
})
r = s.get(url)
time.sleep(.5)
soup = BeautifulSoup(r.content, 'html.parser')
viewstate = soup.find('input', {'name': '__VIEWSTATE' }).get('value')
viewstategen = soup.find('input', {'name': '__VIEWSTATEGENERATOR' }).get('value')
validation = soup.find('input', {'name': '__EVENTVALIDATION' }).get('value')
for ber in _range:
data = {
'ctl00$DefaultContent$BERSearch$dfSearch$txtBERNumber': ber,
'ctl00$DefaultContent$BERSearch$dfSearch$Bottomsearch': 'Search',
'__VIEWSTATE' : viewstate,
'__VIEWSTATEGENERATOR' : viewstategen,
'__EVENTVALIDATION' : validation,
}
y = s.post(url, data=data)
if 'No results found' in y.text:
#print('Invalid ID Number')
pass
else:
#print('Valid ID Number')
hit_list.append(ber)
if __name__=='__main__': #not 100% clear on what exactly this does, but that's a lesson for another day.
#Using threads to call the function
workers = 20
with cf.ThreadPoolExecutor(max_workers=workers) as e:
IDs = range(startrange,end_range)
cs = 20
ranges = [IDs[i+1 :i+cs] for i in range(-1, len(IDs), cs)]
results = e.map(id_filter, ranges)
#below is code for saving the data to an excel file, I've left it out for parsimony.
hit_list
одновременно? - person SeánMcK   schedule 26.05.2016id_filter
работает нормально (но медленно) на всем файле, но используя больше чем 1 поток дает неправильный результат, то либо фрагменты, которые вы передаетеid_filter
, не являются тем, чем вы их считаете, или есть какой-то другой аспект среды потоков, вызывающий проблемы. Работает лучше или хуже с 2 работниками, чем с 1? С 3, а не с 2? Образец появится. - person Peter Rowell   schedule 27.05.2016hit_list
основной программе?map
обычно работает с функциями, которые что-то возвращают. 9/214≈1/20 попаданий с 20 воркерами — это примерный показатель для одного из воркеров, работающих в основном контексте. Кстати, именно поэтомуif __name__=='__main__'
необходимо; остальные рабочие импортируют модуль на win32 (на posix они форкаются). - person Yann Vernier   schedule 27.05.2016return
делать. Но мой ответ ниже, кажется, может нормально работать, ничего не возвращая. Мысли? - person SeánMcK   schedule 27.05.2016