【问题标题】:*Update: How to parse html with python/ beautifulsoup*更新:如何使用 python/beautifulsoup 解析 html
【发布时间】:2013-05-13 18:11:53
【问题描述】:

首先,我对 Python 还是很陌生。我正在尝试从离线网站上抓取联系信息并将信息输出到 csv。我想获取页面 url(不确定如何从 html 中执行此操作)、电子邮件、电话、位置数据(如果可能)、任何名称、任何电话号码以及 html 站点的标语行(如果存在)。


更新 #2 代码:

import os, csv, re
from bs4 import BeautifulSoup

topdir = 'C:\\projects\\training\\html'
output = csv.writer(open("scrape.csv", "wb+"))
output.writerow(["headline", "name", "email", "phone", "location", "url"])
all_contacts = []

for root, dirs, files in os.walk(topdir):
    for f in files:
        if f.lower().endswith((".html", ".htm")):
            soup = BeautifulSoup(f)

            def mailto_link(soup):          
            if soup.name != 'a':
                return None
            for key, value in soup.attrs:
                if key == 'href':
                    m = re.search('mailto:(.*)',value)
                if m:
                    all_contacts.append(m)
                return m.group(1)
            return None

            for ul in soup.findAll('ul'):
            contact = []
            for li in soup.findAll('li'):
                s = li.find('span')
                if not (s and s.string):
                    continue
                if s.string == 'Email:':
                    a = li.find(mailto_link)
                    if a:
                    contact['email'] = mailto_link(a)
                elif s.string == 'Website:':
                    a = li.find('a')
                    if a:
                    contact['website'] = a['href']
                elif s.string == 'Phone:':
                    contact['phone'] = unicode(s.nextSibling).strip()
            all_contacts.append(contact)
            output.writerow([all_contacts])

print "Finished"

此输出当前不返回除行标题以外的任何内容。我在这里想念什么?这应该至少从 html 文件返回一些信息,也就是这个页面:http://bendoeslife.tumblr.com/about

【问题讨论】:

  • 你通常不能从页面HTML中获取页面URL;您需要在获取时保存它。至于其余的……我们需要查看一些示例数据来告诉您解析器出了什么问题。

标签: python html csv web-scraping beautifulsoup


【解决方案1】:

这里有(至少)两个问题。

首先,f 是一个文件名,不是文件内容,也不是由这些内容制成的汤。所以,f.find('h2') 会在文件名中找到'h2',这不是很有用。

其次,大多数find 方法(包括您所调用的str.find)返回一个索引,而不是子字符串。在该索引上调用 str 只会为您提供数字的字符串版本。例如:

>>> s = 'A string with an h2 in it'
>>> i = s.find('h2')
>>> str(i)
'17'

所以,你的代码正在做这样的事情:

>>> f = 'C:\\python\\training\\offline\\somehtml.html'
>>> headline = f.find('h2')
>>> str(headline)
'-1'

您可能希望调用soup 对象上的方法,而不是fBeautifulSoup.find 返回汤的“子树”,这正是您要在此处字符串化的内容。

但是,如果没有您的示例输入,就无法对其进行测试,因此我不能保证这是您代码中的唯一问题。

同时,当您遇到此类问题时,您应该尝试打印出中间值。打印出fheadlineheadline2,这样headline3的错误就更明显了。


只需在find 调用中将f 替换为soup,并修复缩进错误,针对示例文件http://bendoeslife.tumblr.com/about 运行即可。

然而,它并没有做任何有用的事情。由于文件中的任何位置都没有h2 标记,因此headlineNone 结尾。大多数其他领域也是如此。 确实找到任何东西的唯一东西是url,因为您要求它找到一个空字符串,这会发现something是任意的。使用三种不同的解析器,我得到<p>about</p><html><body><p>about</p></body></html>,以及<html><body></body></html>...

您需要真正了解您尝试解析的文件的结构,然后才能对其进行任何有用的操作。例如,在这种情况下,有一个电子邮件地址,但它位于标题为 "Email"<a> 元素中,以及带有 id"email"<li> 元素中。因此,您需要编写一个 find 来根据其中一个条件或它实际匹配的其他条件来定位它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-06
    • 2014-03-06
    • 2011-07-21
    • 2018-07-10
    • 2013-12-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多