我正在尝试构建一个刮刀,它通过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])
我从其他一些例子中获取了代码,因此任何一般性建议也非常受欢迎
答案 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。