当集合列表可以为空时,无法处理列表中具有多个元素的集合列表

Unable to process list of sets having multiple element in list when list of set can be empty

当我为每个网站上的所有电子邮件抓取网站并尝试输出它时,我可以获得给定的数据框,它是每个网站的多个元素集的列表:

URL_WITH_EMAILS_DF = pd.DataFrame(data=[{'main_url': 'http://keilstruplund.dk', 'emails': [{'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}, set(),{'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}, {'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}, {'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}, {'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}, {'ole.norlin@mail.dk', 'ole.gregersens@hk.dk', 'ole.gregersen@hk.dk'}, {'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}, {'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}, {'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}, {'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}, {'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}, {'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}, {'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}, {'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}, {'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}, {'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}, {'prima-rent@youseepost.dk', 'jb@rentind.dk', 'frisoren01@gmail.com', 'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}, {'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}, {'stigterndrup@gmail.com', 'psn@psn.dk', 'samuel@malerfirmaet-lykkebo.dk', 'jan@mundt-reklame.dk', 'ole.norlin@mail.dk', 'nordsjalland@phonixtag.dk', 'jp@rudersdalmaleren.dk', 'vvs@hestetangen.dk', 'steenkragelund@mail.tele.dk', 'ole.gregersen@hk.dk'}, {'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}, {'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}, {'ole.norlin@mail.dk', 'kasserer@keilstruplund.dk', 'ole.gregersen@hk.dk'}, {'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}, {'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}, {'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}, {'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}, {'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}, {'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}, {'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}, {'ole.norlin@mail.dk', 'ole.gregersen@hk.dk'}]}, 
                                    {'main_url': 'http://kirsebaergaarden.com', 'emails': [{'info@kirsebaergaarden.com'}, {'info@kirsebaergaarden.com'}, {'info@kirsebaergaarden.com'}, {'info@kirsebaergaarden.com'}, {'info@kirsebaergaarden.com'}, {'info@kirsebaergaarden.com'}, {'info@kirsebaergaarden.com'}, {'info@kirsebaergaarden.com'}, {'info@kirsebaergaarden.com'}, {'soesterb@gmail.com', 'info@kirsebaergaarden.com'}, {'info@kirsebaergaarden.com'}, {'info@kirsebaergaarden.com'}, {'info@kirsebaergaarden.com'}, {'info@kirsebaergaarden.com'}, {'info@kirsebaergaarden.com'}]},
                                     {'main_url': 'http://koglernes.dk', 'emails': [{'info@koglernes.dk'}, {'info@koglernes.dk'}, {'info@koglernes.dk'}, {'info@koglernes.dk'},set(), set(), {'info@koglernes.dk'}, {'info@koglernes.dk'}]},
                                      {'main_url': 'http://kongehojensbornehave.dk', 'emails': [set()]}
                                   ])

但是,我想将数据框处理成如下所示:

URL_WITH_EMAILS_DF = pd.DataFrame(data=[{'main_url': 'http://keilstruplund.dk', 'emails': ['ole.norlin@mail.dk', 'ole.gregersen@hk.dk', 'prima-rent@youseepost.dk', 'jb@rentind.dk', 'frisoren01@gmail.com','stigterndrup@gmail.com', 'psn@psn.dk', 'samuel@malerfirmaet-lykkebo.dk', 'jan@mundt-reklame.dk',  'nordsjalland@phonixtag.dk', 'jp@rudersdalmaleren.dk', 'vvs@hestetangen.dk', 'steenkragelund@mail.tele.dk', 'kasserer@keilstruplund.dk']},                                        
                                     {'main_url': 'http://kirsebaergaarden.com', 'emails': ['info@kirsebaergaarden.com']},
                                     {'main_url': 'http://koglernes.dk', 'emails': ['info@koglernes.dk']},
                                      {'main_url': 'http://kongehojensbornehave.dk', 'emails': []}
                                   ])

如何实现?

我尝试了以下代码,但它只能设法 return 第一组的第一个元素,而当电子邮件列表中没有元素时 运行 出错 对于给定的网站:

URL_WITH_EMAILS_DF['emails'] = [', '.join(x.pop()) if not None else "" for x in URL_WITH_EMAILS_DF['emails'].values]

P.S:

  1. 根据第一个数据框,我需要插入一组多封电子邮件,因为一个网站可以有多个网页,我不想从每个网页中获取重复的电子邮件
  2. 如果一个列表有[set(), set()] 或[],它应该被认为是空的。此外,如果 set() 可用作 'emails' 上的值,它只会抛出“类型错误:'NoneType' 对象不可迭代”。
  3. 感谢Chris,他在这里提供了解决方案。但是,它显示第 2 点中提到的错误。解决方法如下:
from itertools import chain
        URL_WITH_EMAILS_DF['emails'] = URL_WITH_EMAILS_DF.emails.apply(lambda x: list(set(chain.from_iterable(x))))

您可以编写一个函数来通过联合组合集合,然后在将其转换为列表时执行过滤:

def combine_sets(list_of_sets):
    output = set()    
    for one_set in list_of_sets:
        output = output.union(one_set)

    # Do whatever filtering you need here
    return list(email if email is not None else '' for email in output)

那么您的代码将是:

URL_WITH_EMAILS_DF['emails'] = URL_WITH_EMAILS_DF['emails'].map(combine_sets)

另外,关于您的:

URL_WITH_EMAILS_DF['emails'] = [', '.join(x.pop()) if not None else "" for x in URL_WITH_EMAILS_DF['emails'].values]

您正在检查 if not None,它的计算结果始终为 True,您应该输入 if x is not None

使用集合并集的简单列表理解,这应该是最快的:

URL_WITH_EMAILS_DF['emails'] = [list(set.union(*s))
                                for s in URL_WITH_EMAILS_DF['emails']]

输出:

                         main_url                                                                                                                                                                                                                                                                                                                                                   emails
0         http://keilstruplund.dk  [ole.gregersen@hk.dk, kasserer@keilstruplund.dk, jan@mundt-reklame.dk, nordsjalland@phonixtag.dk, vvs@hestetangen.dk, ole.norlin@mail.dk, frisoren01@gmail.com, stigterndrup@gmail.com, jb@rentind.dk, psn@psn.dk, prima-rent@youseepost.dk, samuel@malerfirmaet-lykkebo.dk, steenkragelund@mail.tele.dk, jp@rudersdalmaleren.dk, ole.gregersens@hk.dk]
1     http://kirsebaergaarden.com                                                                                                                                                                                                                                                                                                          [soesterb@gmail.com, info@kirsebaergaarden.com]
2             http://koglernes.dk                                                                                                                                                                                                                                                                                                                                      [info@koglernes.dk]
3  http://kongehojensbornehave.dk                                                                                                                                                                                                                                                                                                                                                       []

来自表示集合列表的字符串

from ast import literal_eval

URL_WITH_EMAILS_DF['emails'] = [list(set.union(*literal_eval(s)))
                                for s in URL_WITH_EMAILS_DF['emails']]

或者,如果您的字符串格式不正确,并且假设您的电子邮件地址中没有单引号,您可以使用正则表达式:

import re
URL_WITH_EMAILS_DF['emails'] = [list(set(re.findall("'([^']+@[^']+)'", s)))
                                for s in URL_WITH_EMAILS_DF['emails']]