【问题标题】:Web scraper returning list of elements网页爬虫返回元素列表
【发布时间】:2013-11-07 20:14:22
【问题描述】:

我正在尝试构建一个刮板,通过 mechanize 和 lxml 从多个网页上的表格中刮取信息。下面的代码返回一个元素列表,我正在尝试找到一种从这些元素中获取文本的方法(添加 .text 不适用于列表对象)

代码如下:

import mechanize
import lxml.html as lh
import csv

br = mechanize.Browser()
response = br.open("http://localhost/allproducts")

output = csv.writer(file(r'output.csv','wb'), dialect='excel')

for link in br.links(url_regex="product"):
    follow = br.follow_link(link)
    url = br.response().read()
    find = lh.document_fromstring(url)
    find = find.findall('.//td')
    print find
    output.writerows([find])

如果我将以下内容添加到上面的代码末尾,来自 tds 的文本出现在 csv 文件中,但来自每个 td 的文本出现在单独的行上,我希望格式与上面的代码只是文本而不是元素列表(每页的所有信息都在一行上)

for find in find:
    print find.text
    output.writerows([find.text])

我从一堆其他示例中获取了代码,因此也非常感谢任何一般性建议

【问题讨论】:

    标签: python python-2.7 web-scraping mechanize lxml


    【解决方案1】:

    你离得太近了!您的代码有 2 个问题:

    1) find 是一个对象列表,而不是字符串列表。这里有一些 python 来验证这一点:

    >>> type(find)
    <type 'list'>
    >>> find
    [<Element td at 0x101401e30>, <Element td at 0x101401e90>, <Element td at 0x101401ef0>, <Element td at 0x101401f50>, <Element td at 0x101401fb0>, <Element td at 0x101404050>, <Element td at 0x1014040b0>, <Element td at 0x101404110>, <Element td at 0x101404170>, <Element td at 0x1014041d0>, <Element td at 0x101404230>, <Element td at 0x101404290>, <Element td at 0x1014042f0>, <Element td at 0x101404350>, <Element td at 0x1014043b0>, <Element td at 0x101404410>]
    >>> type(find[0])
    <class 'lxml.html.HtmlElement'>
    

    我们会说find 变量指向&lt;class 'lxml.html.HtmlElement'&gt; 对象的列表。这种类型的结构不应直接传递给output.writerows。相反,此函数将获取文本项列表。

    2) 迭代find 对象时,您正在重新分配变量名称find。迭代时切勿使用与您正在迭代的项目名称相同的名称!

    for item in find:
        print item.text
        output.writerows([item.text])
    

    把它们放在一起,你应该有这样的东西:

    for link in br.links(url_regex="product"):
        follow = br.follow_link(link)
        url = br.response().read()
        find = lh.document_fromstring(url)
        find = find.findall('.//td')
        print find
        results = []  # Create a place to store the text names
        for item in find:
            results.append(item.text)  # Store the text name of the item in the results list.
        output.writerows(results)  # Now, write the results out.  # EDITED to use correct variable here.
    

    专业提示

    您甚至可以使用列表推导生成单行结果,如下所示:

    results = [item.text for item in find]
    output.writerows(results)
    

    这会将 3 行 python 替换为一行。

    【讨论】:

    • 非常好,非常感谢。上面代码中唯一需要的更改是将 output.writerows([find.text]) 更改为 output.writerows([results]),专业提示中的代码第一次完美运行
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多