Используйте многопроцессорную обработку и BeautifulSoup для очистки веб-страниц, используйте MaybeEncodingError и RecursionError - PullRequest
0 голосов
/ 01 сентября 2018

Я работаю над веб-проектом. Первое раскрывающееся меню содержит около 800 параметров, а второе раскрывающееся меню содержит более 20 значений. Процесс делает это очень медленно. Поэтому я попытался использовать многопроцессорность в надежде, что это может немного ускорить процесс. Тем не менее, я получил сообщения об ошибках, которые я не мог решить.

Мои коды:

def create_df(city_var, year_var):
    city = Select(driver.find_element_by_css_selector("select[id*='Main_csCity_ddlEntity1']"))
    city.select_by_visible_text(city_var) 
    year = Select(driver.find_element_by_css_selector("select[id*='Main_csCity_ddlYear1']"))
    year.select_by_visible_text(year_var) 
    try:
        driver.find_element_by_xpath('//input[@type="submit"]').click()
    except Exception as e:
        time.sleep(1)
        driver.find_element_by_xpath('//input[@type="submit"]').click()
        print('something wrong:'+city_var+year_var)
    html = driver.page_source
    soup = BeautifulSoup(html, "lxml")
    try:
        small_header = soup.find_all("div",{"class":"ResultsHeader"})
        ret_list = []
        for idx, span in enumerate(small_header[0].find_all("span")):
            if idx in [1,3,5,7]:
                ret_list.append(span.contents[0])
    except:
        print(city_var+year_var)
    try:
        second_header = soup.find_all("tr",{"class":re.compile('Detail.*')})
        ret_list2 = []
        for idx, content in enumerate(second_header):
            if len(content.contents) == 3:
                ret_list2.append([content.contents[1].contents[0], '', '', ''])
            elif len(content.contents) == 7:
                sublist = []
                for idx2 in range(5):
                    if idx2 == 1:
                        continue
                    sublist.append(content.contents[idx2+1].contents[0])
                ret_list2.append(sublist)
            else:
                print('WRONG')
    except:
        print(city_var+year_var)
    ret_list3 = ret_list2[1:]
    ret_list4 = [ret_list+sub for sub in ret_list3]
    return pd.DataFrame(ret_list4)
list_of_city_year = [[x,y] for x in cities1 for y in years]
def return_df(list1):
    df = pd.DataFrame()
    c = list1[0]
    y = list1[1]
    df = df.append(create_df(c, y))
    return df
with Pool(5) as p:
    records = p.map(return_df, list_of_city_year[:100])

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

MaybeEncodingError Traceback (самый последний вызов последний) в () 1 с бассейном (5) в качестве p: ----> 2 записи = p.map (return_df, list_of_city_year [: 100])

~ / anaconda3 / lib / python3.6 / multiprocessing / pool.py в карте (self, func, повторяемый, размер) 264 в списке, который возвращается. 265 '' ' -> 266 вернуть self._map_async (func, iterable, mapstar, chunksize) .get () 267 268 def starmap (self, func, iterable, chunksize = None):

~ / anaconda3 / lib / python3.6 / multiprocessing / pool.py в get (self, тайм-аут) 642 возвращают self._value 643 еще: -> 644 поднять self._value 645 646 def _set (self, i, obj):

MaybeEncodingError: Ошибка при отправке результата: '[0 1 2
3 4 5 \ ..... ..... ....]. Причина: 'RecursionError (' превышена максимальная глубина рекурсии при вызове объекта Python ',)'

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

1 Ответ

0 голосов
/ 12 июля 2019

такой MaybeEncodingError в основном из-за того, что вы забыли использовать if __name__ == '__main__': при попытке создать рабочую версию в Windows у меня появлялось странное повторяющееся сообщение об ошибке.

Attempt to start a new process before the current process
has finished its bootstrapping phase.

This probably means that you are on Windows and you have
forgotten to use the proper idiom in the main module:

if __name__ == '__main__': буквально цитируя полученный комментарий, поскольку он говорит само за себя:

ошибка в окнах заключается в том, что каждый процесс порождает новый процесс python, который интерпретирует файл python и т. Д., Поэтому все, что находится за пределами "if main block", выполняется снова "

чтобы быть переносимым, вы должны использовать if __name__=='__main__' при запуске этого модуля:

import multiprocessing as mp
from multiprocessing import Pool, freeze_support


if __name__ == '__main__':  #you need this in windows
    freeze_support() 
    main()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...