scikit learn 潜在狄利克雷分配在多处理和 url 请求后挂起



一般来说,我的python代码会执行以下三个步骤

  1. 运行多进程以从搜索引擎中抓取搜索结果
  2. 使用 Python 请求库从列表中的每个 URL 中抓取文本(无需多处理)
  3. 从scikit学习库运行LDA类对象的fit_partial方法

当我只抓取总共 50~80 个 url 时,程序运行良好,但是当URL很多时,程序在完成三到八个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 挂起。波纹管是步骤 2 的代码。所有结果都添加到使用 url 作为键的字典对象中

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("trn ") 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}}

波纹管是步骤 3 的代码。 g_result_lda.model 是 scikit-learn LatentDirichletAllocation 类对象。 corpus_data是从 url 文本创建的文档单词矩阵

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库与请求库有冲突吗?

我正在OSX上学习python

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

相关内容

  • 没有找到相关文章