【问题标题】:How to extract text inside span without class name with BeautifulSoup in python如何在python中使用BeautifulSoup在没有类名的范围内提取文本
【发布时间】:2020-02-18 23:45:59
【问题描述】:

我正在制作一本字典,用于查找西班牙语中的单词并为我提供相应的英文翻译。我是BeautifulSoup 的新手,所以我利用这个机会学习网络抓取。

网页链接是https://www.spanishdict.com/translate/rojo。 我只是输入了“rojo”作为示例。

但是,在我成功提取翻译后,我也想提取一些例句,但在这里我遇到了一个问题。我无法提取 <span> WITHOUT 类名中的任何一个句子。

我试过了

soup.find_all(name='div', class_='indent--FyTYr')

但是该类中弹出了许多不必要的信息。 我还注意到the link 提到previous_sibling 的帖子中的一个答案,但它没有用。

示例 html 代码如下所示:

<div class="indent--FyTYr">
  <div>
    <span>The sky turned red at sundown.</span>
    <span class="dash--SIa20"></span>
    <em class="exampleDesktop--3n1hN">El cielo se tornó rojo al atardecer.</em> 
  </div>
...
</div>

我想从上面的 html 示例代码中提取句子。但是我还没有找到任何有用的方法来定位和提取。

日落时天空变红了。

【问题讨论】:

    标签: python html web-scraping beautifulsoup


    【解决方案1】:

    如果您确定span 将是第一个,您可以简单地使用.find("span")

    >>> soup.find_all(name='div', class_='indent--FyTYr')[0].find("span").text
    'The sky turned red at sundown.'
    

    【讨论】:

    • 嗯。我不认为这是我想要的,因为最终我想搜索这个词,并且它们的例句相应地出现。所以我不能提前知道这句话。不过还是谢谢你的建议。
    【解决方案2】:

    您可以提供 css 选择器列表并生成匹配元素列表,然后生成字典以查找翻译。交换顺序,所以英语短语是键,西班牙语是值。需要 bs4 4.7.1+。匹配的项目是您有短语的所有项目 - 翻译。

    from bs4 import BeautifulSoup as bs
    import requests
    
    r = requests.get('https://www.spanishdict.com/translate/rojo')
    soup = bs(r.content, 'lxml')
    elems = [i.text for i in soup.select('span:has(+[class^="dash--"]), div:has(span:has(+[class^="dash--"])) em:not([title]), .ex, .ex_unit .tran_group, .idm, .idm_unit .tran_group, .cpd, .cpd_group .tran_group')]
    results = {v if k!=elems[0] else k:k if k!=elems[0] else v for k,v in zip(elems[0::2],elems[1::2])} #reverse first item
    print(results)
    

    否则,您也可以列出切片对。

    【讨论】:

      【解决方案3】:

      您可以使用递归函数遍历id='dictionary-neodict-es' 的最外层div,以说明存在多个嵌套divs 和indent--FyTYr 类的事实:

      from bs4 import BeautifulSoup as soup
      import requests, bs4
      def has_class(d, c):
         return any(c in i.attrs.get('class', []) or has_class(getattr(i, 'contents', []), c) for i in d if i != '\n' and not isinstance(i, bs4.NavigableString))
      
      def get_sentences(d):
         if 'indent--FyTYr' in d.attrs.get('class', []) and not has_class(d.contents, 'indent--FyTYr'):
            yield [d.div.span.text, d.div.em.text]
         else:
            for i in filter(lambda x:x != '\n' and not isinstance(x, bs4.NavigableString), getattr(d, 'contents', [])):
               yield from get_sentences(i)
      
      
      result = list(get_sentences(soup(requests.get('https://www.spanishdict.com/translate/rojo').text, 'html.parser').find('div', {'id':'dictionary-neodict-es'})))
      

      现在,您可以访问所有句子了:

      [['The sky turned red at sundown.', 'El cielo se tornó rojo al atardecer.'], ['No quiero ver esa propaganda roja.', "I don't want to see that red propaganda."], ['Ella cree que me veo mejor vestida de rojo, pero no estoy segura.', "She thinks I look best dressed in red, but I'm not sure."], ['Durante la Guerra Fría, a los izquierdistas se les llamaba rojos.', 'During the Cold War, the leftists were called reds.']]
      

      要访问您想要的字符串:

      print(result[0][0])
      

      输出:

      'The sky turned red at sundown.'
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-12-05
        • 1970-01-01
        • 2019-07-23
        • 2013-11-06
        • 1970-01-01
        • 2019-06-25
        • 1970-01-01
        • 2018-03-04
        相关资源
        最近更新 更多