代码之家  ›  专栏  ›  技术社区  ›  alphazwest

合并尝试:Beaufulsoup4中的块除外

  •  1
  • alphazwest  · 技术社区  · 6 年前

    这可能是一个比我的用例所提出的问题要广泛得多的问题。

    我正在使用BeautifulSoup从HTML文档中提取数据。

    对于那些不熟悉beautifulsoup的人来说,它本质上是解析一个HTML字符串,并使用类方法搜索和隔离特定的数据,给出明确的指令。

    第一步: soup = Beautifulsoup(html_string)

    第二步: title= soup.find('h1').get_text()

    步骤1解析文档,步骤2提供要提取哪些数据的说明,在上述情况下,使用 get_text() ,还有一些格式。

    我通常有一个这样的行为列表,其中可能存在数据,也可能不存在数据,并且这两种情况都是可以接受的。例如,在一系列配置文件页面上,某些用户可能 favorite_color , favorite_movie etc 进入。如果有数据,我想要它,但是如果没有,一个 None 价值是好的。

    我通常是这样处理这些案例的:

    soup = Beautifulsoup(html)
    
    try:
        data_one = soup.find('div', class_='data_one').get_text()
    except AttributeError as e:
        data_one = None
    
    try:
        data_two= soup.find('div', class_='data_two').get_text()
    except AttributeError as e:
        data_two= None
    
    try:
        data_three = soup.find('div', class_='data_three ').get_text()
    except AttributeError as e:
        data_three = None
    

    可以想象,我的文件很快就会变大,很难导航。

    什么是最 干的 如何解决这个问题?

    注意:在我的用例中, 每一个 try:except 块将处理单个异常类, AttributeError 它代表HTML中缺少的数据。

    注意:我正在寻找一些不会限制提取方法类型的东西。例如,这也是我想要使用的:

    try:
        list_items = [x.get_text() for x in soup.find('div', class_='first').find_all('li', class_='first-child') and x.find('a', class_='conditional-link') is not None]
    except AttributeError as e:
        list_items = None      
    

    更新日期:2018年12月30日 我仍然认为被接受的答案是最正确的方法。与其他方法相比,我也觉得这有点抽象。我想在这里加入另一种方法。首先,我要说的是,这个问题试图解决的核心问题之一是,当数据可能不是数据时,使用漂亮的汤进一步访问数据。例如, GETX文本() 方法引发 属性错误 关于的元素 NoneType 班级。

    这是一种替代方法,在这种情况下,需要进一步的规范来从元素列表中提取数据,这些元素可能包括,也可能不包括 非类型 元素:

    # Get Initial Elements (NoneType assigned if Error)
    data_one = soup.find('element', class_='e_one class_name')
    data_two = soup.find('elemment', value='1')
    data_three = soup.find('element', class_='parent').find('div', class_='name')
    
    # Further parsing/extraction if element is not NoneType Object
    data = [x.get_text(strip=True) if x is not None for x in [data_one, data_two, data_three]]
    

    这不是革命性的,但似乎提供了一种非常灵活的巩固方式。 一些 部分代码。

    3 回复  |  直到 6 年前
        1
  •  2
  •   alecxe    6 年前

    或者,你可以只用 getattr() 内置函数 LBYL 方式:

    data_one = getattr(soup.find('div', class_='data_one'), 'text', None)
    data_two = getattr(soup.find('div', class_='data_two'), 'text', None)
    data_three = getattr(soup.find('div', class_='data_three'), 'text', None)
    
        2
  •  1
  •   alecxe    6 年前

    Extract a method :

    def get_text_or_none(element)
        try:
            return element.get_text()
        except AttributeError:
            return None
    
    data_one = get_text_or_none(soup.find('div', class_='data_one'))
    data_two = get_text_or_none(soup.find('div', class_='data_two'))
    data_three = get_text_or_none(soup.find('div', class_='data_three'))
    

    这就是 EAFP 方法。

    LBYL 人们会这样做:

    return element.get_text() if element else None
    
        3
  •  0
  •   alecxe    6 年前

    更具体的情况是,处理方法可能是循环类值列表:

    classes = ['data_one', 'data_two', 'data_three']
    
    result = {}
    for class_value in classes:
        try:
            result[class_value] = soup.find('div', class_=class_value).get_text()
        except AttributeError:
            result[class_value]
    
    print(result)