【问题标题】:Can't figure out the right loop in scrapy无法在scrapy中找出正确的循环
【发布时间】:2012-09-15 05:00:27
【问题描述】:

我是新手。

这是我的蜘蛛:

from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
from scrapy.selector import HtmlXPathSelector
from ampa.items import AmpaItem

class AmpaSpider(CrawlSpider):
    name = "ampa"
    allowed_domains = ['website']
    start_urls = ['website/page']


rules = (Rule(SgmlLinkExtractor(allow=('associados?', ), deny=('associado/', )), callback='parse_page', follow=True),)

def parse_page(self, response):
    hxs = HtmlXPathSelector(response)
    item = AmpaItem()
    farmers = hxs.select('//div[@class="span-24 tx_left"]')
    item['nome'] = farmers.select('//div/h3[@class="titulo"]/a/text()').extract()
    item['phone'] = farmers.select('//div/span[@class="chamada"]/a[contains(text(), "Telefone")]/text()').extract() 
    item['email'] = farmers.select('//div/span[@class="chamada"]/a[contains(text(), "E-mail")]/text()').extract()
    print item.values()
    return item

这是我的管道:

class CsvWriterPipeline(object):

def __init__(self):
    self.csvwriter = csv.writer(open('items.csv', 'wb'))

def process_item(self, item, ampa):
    self.csvwriter.writerow([item['nome'], item['phone'], item['email']])   
    return item

网站的每个页面都有一个姓名、电话和电子邮件列表。上面的代码将输出一个 csv 文件,每页包含三列和一行。在第一列中,每个单元格是该页面中所有姓名的列表,在第二列中,它们是所有电话的列表,在第三列中,它们是所有电子邮件的列表。

我真正想做的是将每个姓名、电话和电子邮件放在单独的行中。我尝试通过循环遍历每个项目来做到这一点,但它只打印名字,每个页面上的电话和电子邮件。 (是不是因为每次函数蜘蛛返回一个项目时,回调将爬虫移动到下一个URL)(是吗???)

你会怎么做呢?

这是项目:

from scrapy.item import Item, Field

class AmpaItem(Item):
nome = Field()
phone = Field()
email = Field()

【问题讨论】:

  • 你能打印出itemprocess_item 函数中的内容吗?它看起来根本不应该是电子邮件列表...
  • 在您的电子表格查看器中,您是否确保以“,”作为分隔符打开 csv?
  • 您好 dm03514,我使用了分隔符,但它仍然无法分隔项目。
  • 你能在保存之前发布一个示例item,当它在process_item 中时?

标签: python scrapy


【解决方案1】:

根据您在farmes 中使用的复数形式,我假设页面上有很多农民。所以你的表达式可能会返回一个农民的集合。

你能遍历农民的结果并产出每个项目吗?

#pseudocode
hxs = HtmlXPathSelector(response)
farmers = hxs.select('//div[@class="span-24 tx_left"]')
for farmer in farmer:
    item = AmpaItem()
    #be sure to select only one desired farmer here
    item['nome'] = farmers.select('//div/h3[@class="titulo"]/a/text()').extract()
    item['phone'] = farmers.select('//div/span[@class="chamada"]/a[contains(text(), "Telefone")]/text()').extract() 
    item['email'] = farmers.select('//div/span[@class="chamada"]/a[contains(text(), "E-mail")]/text()').extract()
    yield item

【讨论】:

  • DrColossos,是的,每页有几个农民。我之前曾尝试遍历农民的结果,它要么在一个单元格中返回所有农民,要么只返回每页上的第一个农民。不知道是不是被回调调用了?
  • 如果您将链接发布到actuel 网站,会更容易。这可能只是 XPath 表达式的问题
  • www.ampa.com.br/home/associados/
  • 链接在上面,Colossos 博士。我感谢您的帮助。在这里努力学习 Scrapy...
【解决方案2】:

我通过更改管道找到了解决方案:

import csv
import itertools

class CsvWriterPipeline(object):

def __init__(self):
    self.csvwriter = csv.writer(open('items.csv', 'wb'), delimiter=',')

def process_item(self, item, ampa):
    for i,n,k in itertools.izip(item['nome'],item['phone'],item['email']):  
        self.csvwriter.writerow([i,n,k])    
    return item

感谢 DrColossos 和 dm03514!

这是我关于stackoverflow的第一个问题!!

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2021-10-29
  • 2021-04-03
  • 1970-01-01
  • 1970-01-01
  • 2018-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多