Web scraper返回元素列表

时间:2013-11-07 20:14:23

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

我正在尝试构建一个刮刀,它通过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])

我从其他一些例子中获取了代码,因此任何一般性建议也非常受欢迎

1 个答案:

答案 0 :(得分:0)

你太近了!你的代码有两个问题:

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变量指向<class 'lxml.html.HtmlElement'>个对象的列表。不应将此类结构直接传递给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。