scikit learn LatentDirichletAllocation在多处理和url请求后挂起

时间:2016-01-22 02:55:46

标签: python-3.x scikit-learn python-requests python-multiprocessing

通常,我的python代码遵循三个步骤

  1. 运行多进程以从搜索引擎中搜索搜索结果
  2. 使用python请求库
  3. 从列表中的每个URL中删除文本(不进行多处理)
  4. 从scikit learn library运行LDA类对象的fit_partial方法
  5. 当我只有50~80个网址时,程序运行正常,但是 当有很多网址时,程序在完成三到八个fit_partial方法和打印日志后在第3步挂起

    [Parallel(n_jobs=4)]: Done   4 out of   4 | elapsed:    0.1s finished
    [Parallel(n_jobs=4)]: Done   4 out of   4 | elapsed:    0.1s finished
    [Parallel(n_jobs=4)]: Done   4 out of   4 | elapsed:    0.1s finished
    [Parallel(n_jobs=4)]: Done   4 out of   4 | elapsed:    0.1s finished
    

    如果我检查进程cpu使用情况,所有python进程都有零cpu用法

    当我将上述三个步骤分成两个python文件时(一个python脚本执行步骤1和2并使用pickle dump将结果保存为文件,另一个脚本在加载保存的文件后执行步骤3),第二个python文件(其中包含步骤3)运行正常并没有问题。

    所以,我进行了两次模拟。 在第一次模拟中我只省略了第2步。在第二次模拟中只省略了第1步。 在每次模拟中,我加载了步骤1和步骤2的保存结果,而不是运行实际步骤。

    第一次模拟运行正常,但第二次模拟被绞死。

    结论是第2步导致第3步挂起。 Bellow是步骤2的代码。所有结果都添加到使用urls作为键的字典对象

    def parse_information(url):
    
    print(url)
    
    try:
        response = requests.get(url, verify=False)
    except:
        raise Exception("requests exception")
    
    obj_bs = BeautifulSoup(response.text, "html.parser")
    
    meta_refresh = obj_bs.find("meta", {"http-equiv": "refresh"})
    
    if meta_refresh is not None:
        refresh_url = meta_refresh["content"].lower().rsplit("url=")[1]
        rup = urlparse(refresh_url)
        if rup.netloc == "":
            up = urlparse(url)
            return parse_information(up.scheme + "://" + up.netloc + refresh_url)
        return parse_information(refresh_url)
    
    meta_charset = obj_bs.find(lambda tag: tag.name == 'meta' and 'charset' in tag.attrs)
    http_equivs = obj_bs.findAll(lambda tag: tag.name == 'meta' and 'http-equiv' in tag.attrs)
    
    if meta_charset is not None:
        response.encoding = meta_charset["charset"]
    elif len(http_equivs) > 0:
        content_charset = ""
        for http_equiv in http_equivs:
            if http_equiv["http-equiv"].lower() == "content-type":
                content_charset = http_equiv["content"]
                break
        if content_charset != "":
            parse_charset = content_charset.split("charset=")
            if len(parse_charset) > 1:
                response.encoding = parse_charset[1]
        else:
            response.encoding = "shift_jis"
    else:
        response.encoding = "shift_jis"
    obj_bs = BeautifulSoup(response.text, "html.parser")
    
    info_dict = dict(title="", h1="", keywords="", description="", h2="")
    
    tag_title = obj_bs.find("title")
    info_dict["title"] = tag_title.text if tag_title is not None else ""
    
    tag_h1 = obj_bs.find("h1")
    info_dict["h1"] = tag_h1.text if tag_h1 is not None else ""
    
    tags_h2 = obj_bs.findAll("h2")
    info_dict["h2"] = "|".join([tag_h2.text.strip("\t\r\n ") for tag_h2 in tags_h2]) if len(tags_h2) > 0 else ""
    
    metas = obj_bs.findAll(lambda tag: tag.name == 'meta' and 'name' in tag.attrs)
    
    for meta in metas:
        if meta["name"] == "keywords":
            info_dict["keywords"] = meta.get("content", "")
        elif meta["name"] == "description":
            info_dict["description"] = meta.get("content", "")
    
    htot = html2text.HTML2Text()
    htot.ignore_links = True
    htot.images_to_alt = True
    htot.ignore_emphasis = True
    
    pure_text = htot.handle(response.text).lower()
    
    noun_dict = japanese_noun_dict(pure_text)
    
    if len(noun_dict) == 0:
        num_nouns = 0
    else:
        num_nouns = reduce(lambda a, b: a + b, noun_dict.values())
    
    return {"info": info_dict, "noun": {"num": num_nouns, "freq": noun_dict}}
    

    Bellow是第3步的代码.g_result_lda.model是scikit-learn LatentDirichletAllocation类对象。 corpus_data是根据网址文本

    创建的文档字矩阵
    g_result_lda = TextLDA(documents=corpus_data, n_topics=n_topic)
    
    len_corpus = len(g_result_lda.corpus_data)
    
    # g_result_lda.model.fit(g_result_lda.corpus_data)
    
    start_index = 0
    
    while start_index < len_corpus:
    
        end_index = start_index + 20 if start_index + 20 < len_corpus else len_corpus
        g_result_lda.model.partial_fit(g_result_lda.corpus_data[start_index:end_index])
        start_index = start_index +20
    

    有谁知道导致问题的原因是什么? scikit-learn Library是否与请求库发生冲突?

    我正在OSX上学习python

1 个答案:

答案 0 :(得分:0)

我刚刚通过使用RabbitMQ构建RPC服务器解决了这个问题。 我使用Pika库来使用RabbitMQ,并使用BlockingConnection创建了一个服务器。服务器只在一个线程和进程上运行,同时等待一个请求,当它收到请求时,它使用多处理进行LDA分析并返回结果。