【问题标题】:Looping through elements with Beautifulsoup使用 Beautifulsoup 循环遍历元素
【发布时间】:2017-10-19 15:12:28
【问题描述】:

我正在尝试存储从网站上抓取的一些数据。我需要的数据是元素中的文本,然后存储在 csv 中以供以后查询。

在下面的代码中,我找到了对“vip”类的所有引用。然后我想遍历这些以去除不必要的 HTML 以仅获取文本数据。最后我用 utf-8 对其进行编码,准备好插入到 csv 中。

# parse the page and store in var soup
soup = BeautifulSoup(page, 'html.parser')

# find the title
title_box = soup.findAll('a', attrs={'class': 'vip'}}

print title_box

# loop through each iteration
for each in title_box:
    if each.find('title_box'):
        title = title_box.text.strip().encode('utf-8')

# print the result
print title

但是,每当我打印“标题”的结果时,我都会收到以下错误:

Traceback (most recent call last):
  File "/Users/XXXX/Projects/project-kitchenaid/scaper.py", line 28, in <module>
    print title
NameError: name 'title' is not defined

据我了解,title 超出范围。如何从循环中检索数据并将其写入打印调用?

就上下文而言,这只是print title_box 的一个结果:

<a class="vip" href="http://www.ebay.co.uk/itm/KITCHENAID-CLASSIC-MIXER-5K45SS-ATTACHMENTS-AND-INSTRUCTIONS-/302468759209?hash=item466c8afea9:g:2PIAAOSwCi9Zvk2D" title="Click this link to access KITCHENAID CLASSIC MIXER 5K45SS - ATTACHMENTS AND INSTRUCTIONS">KITCHENAID CLASSIC MIXER 5K45SS - ATTACHMENTS AND INSTRUCTIONS</a>]

【问题讨论】:

  • 只有当each.find("title_box")返回任何东西时,你的title变量才会被定义。这意味着在任何迭代中都找不到title_box
  • each.find('title_box') 是做什么的?
  • 啊,我明白了,我要做的是使用('a', attrs={'class': 'vip'})从html中提取数据的每次迭代
  • 将字符串传递给find 方法搜索名称与字符串匹配的标记。因此,当您调用each.find('title_box') 时,您正在尝试查找title_box 标记。你确定那是你想要的吗?如果是class 属性的值,则应使用each.find(attrs={'class': 'title_box'})
  • Mahesh 没错,我要找的是这个if each.find('a', attrs={'class': 'vip'}),所以我的问题是:如何从循环和 if/else 语句中打印这些结果?

标签: python web-scraping beautifulsoup


【解决方案1】:

步骤如下:

  1. title_box = soup.findAll('a', attrs={'class': 'vip'}} 此行查找所有带有标签 "a" 的 html,并使用所需的类 vip 进一步过滤它。
  2. 你不能做if each.find('title_box'):,因为没有名为title_box的html标签
  3. 您可以使用获取文本

    for each in soup: print(each.text.strip().encode('utf-8'))

参考上述摘录,无需进一步使用任何条件语句

【讨论】:

    【解决方案2】:

    我制作了一个 HTML 文件,其中包含您的 a 元素的五个副本,并将其命名为“temp.htm”:

    <a class="vip" href="http://www.ebay.co.uk/itm/KITCHENAID-CLASSIC-MIXER-5K45SS-ATTACHMENTS-AND-INSTRUCTIONS-/302468759209?hash=item466c8afea9:g:2PIAAOSwCi9Zvk2D" title="Click this link to access KITCHENAID CLASSIC MIXER 5K45SS - ATTACHMENTS AND INSTRUCTIONS">KITCHENAID CLASSIC MIXER 5K45SS - ATTACHMENTS AND INSTRUCTIONS</a>
    <a class="vip" href="http://www.ebay.co.uk/itm/KITCHENAID-CLASSIC-MIXER-5K45SS-ATTACHMENTS-AND-INSTRUCTIONS-/302468759209?hash=item466c8afea9:g:2PIAAOSwCi9Zvk2D" title="Click this link to access KITCHENAID CLASSIC MIXER 5K45SS - ATTACHMENTS AND INSTRUCTIONS">KITCHENAID CLASSIC MIXER 5K45SS - ATTACHMENTS AND INSTRUCTIONS</a>
    <a class="vip" href="http://www.ebay.co.uk/itm/KITCHENAID-CLASSIC-MIXER-5K45SS-ATTACHMENTS-AND-INSTRUCTIONS-/302468759209?hash=item466c8afea9:g:2PIAAOSwCi9Zvk2D" title="Click this link to access KITCHENAID CLASSIC MIXER 5K45SS - ATTACHMENTS AND INSTRUCTIONS">KITCHENAID CLASSIC MIXER 5K45SS - ATTACHMENTS AND INSTRUCTIONS</a>
    <a class="vip" href="http://www.ebay.co.uk/itm/KITCHENAID-CLASSIC-MIXER-5K45SS-ATTACHMENTS-AND-INSTRUCTIONS-/302468759209?hash=item466c8afea9:g:2PIAAOSwCi9Zvk2D" title="Click this link to access KITCHENAID CLASSIC MIXER 5K45SS - ATTACHMENTS AND INSTRUCTIONS">KITCHENAID CLASSIC MIXER 5K45SS - ATTACHMENTS AND INSTRUCTIONS</a>
    <a class="vip" href="http://www.ebay.co.uk/itm/KITCHENAID-CLASSIC-MIXER-5K45SS-ATTACHMENTS-AND-INSTRUCTIONS-/302468759209?hash=item466c8afea9:g:2PIAAOSwCi9Zvk2D" title="Click this link to access KITCHENAID CLASSIC MIXER 5K45SS - ATTACHMENTS AND INSTRUCTIONS">KITCHENAID CLASSIC MIXER 5K45SS - ATTACHMENTS AND INSTRUCTIONS</a>
    

    然后我运行这段代码来获取这些链接中的文本:

    >>> page = open('temp.htm').read()
    >>> import bs4
    >>> soup = bs4.BeautifulSoup(page, 'lxml')
    >>> for link in soup.select('.vip'):
    ...     link.text
    ... 
    'KITCHENAID CLASSIC MIXER 5K45SS - ATTACHMENTS AND INSTRUCTIONS'
    'KITCHENAID CLASSIC MIXER 5K45SS - ATTACHMENTS AND INSTRUCTIONS'
    'KITCHENAID CLASSIC MIXER 5K45SS - ATTACHMENTS AND INSTRUCTIONS'
    'KITCHENAID CLASSIC MIXER 5K45SS - ATTACHMENTS AND INSTRUCTIONS'
    'KITCHENAID CLASSIC MIXER 5K45SS - ATTACHMENTS AND INSTRUCTIONS'
    

    您可能仍需要对这些文本进行编码以便存放在您的 csv 文件中。

    【讨论】:

      【解决方案3】:

      正如我在评论中所说,使用 each.find('title_box') 不会获取任何内容,因为没有 title_box 标记。

      由于您需要具有class 属性为vipa 元素,因此您应该检查以下内容:

      if 'vip' in each['class']:
      

      另外,当这行代码运行时:

      title_box = soup.findAll('a', attrs={'class': 'vip'}}
      

      title_box 列表已经填充了a 元素,这些元素的class 属性为vip。因此,您不必在 for 循环中再次检查相同的条件。

      这是您应该尝试的代码:

      for each in title_box:
          title = each.text.strip().encode('utf-8')
          print title
      

      当然,您可以完全取消将文本分配给变量并直接打印它:

      print each.text.strip().encode('utf-8')
      

      【讨论】:

      • 这就是我的想法,但控制台什么也没返回。有什么想法吗?
      • 请看问题底部的摘录在哪里。
      猜你喜欢
      • 2016-05-29
      • 2015-10-08
      • 2018-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-23
      相关资源
      最近更新 更多