在Python脚本中向Scrapy爬虫传递参数

8
我可以在Python脚本中按照维基百科上的以下步骤来运行爬虫:
from twisted.internet import reactor
from scrapy.crawler import Crawler
from scrapy import log, signals
from testspiders.spiders.followall import FollowAllSpider
from scrapy.utils.project import get_project_settings

spider = FollowAllSpider(domain='scrapinghub.com')
settings = get_project_settings()
crawler = Crawler(settings)
crawler.signals.connect(reactor.stop, signal=signals.spider_closed)
crawler.configure()
crawler.crawl(spider)
crawler.start()
log.start()
reactor.run()

正如您所见,我可以将domain传递给FollowAllSpider,但我的问题是如何使用上面的代码将start_urls(实际上是将添加到固定URL的date)传递给我的蜘蛛类?

这是我的蜘蛛类:

class MySpider(CrawlSpider):
    name = 'tw'
    def __init__(self,date):
        y,m,d=date.split('-') #this is a test , it could split with regex! 
        try:
            y,m,d=int(y),int(m),int(d)

        except ValueError:
            raise 'Enter a valid date'

        self.allowed_domains = ['mydomin.com']
        self.start_urls = ['my_start_urls{}-{}-{}'.format(y,m,d)]

    def parse(self, response):
        questions = Selector(response).xpath('//div[@class="result-link"]/span/a/@href') 
        for question in questions:
            item = PoptopItem()
            item['url'] = question.extract()
            yield item['url']

这是我的脚本:

from pdfcreator import convertor
from twisted.internet import reactor
from scrapy.crawler import Crawler
from scrapy import log, signals
#from testspiders.spiders.followall import FollowAllSpider
from scrapy.utils.project import get_project_settings
from poptop.spiders.stackoverflow_spider import MySpider
from poptop.items import PoptopItem

settings = get_project_settings()
crawler = Crawler(settings) 
crawler.signals.connect(reactor.stop, signal=signals.spider_closed)
crawler.configure()

date=raw_input('Enter the date with this format (d-m-Y) : ')
print date
spider=MySpider(date=date)
crawler.crawl(spider)
crawler.start()
log.start()
item=PoptopItem()

for url in item['url']:
    convertor(url)

reactor.run() # the script will block here until the spider_closed signal was sent

如果我只打印item,将会得到以下错误:
2015-02-25 17:13:47+0330 [tw] ERROR: Spider must return Request, BaseItem or None, got 'unicode' in <GET test-link2015-1-17>

项目:

import scrapy


class PoptopItem(scrapy.Item):
    titles= scrapy.Field()
    content= scrapy.Field()
    url=scrapy.Field()
1个回答

9

您需要修改__init__()构造函数以接受date参数。另外,我建议使用datetime.strptime()来解析日期字符串:

from datetime import datetime

class MySpider(CrawlSpider):
    name = 'tw'
    allowed_domains = ['test.com']

    def __init__(self, *args, **kwargs):
        super(MySpider, self).__init__(*args, **kwargs) 

        date = kwargs.get('date')
        if not date:
            raise ValueError('No date given')

        dt = datetime.strptime(date, "%m-%d-%Y")
        self.start_urls = ['http://test.com/{dt.year}-{dt.month}-{dt.day}'.format(dt=dt)]

然后,您可以按照以下方式实例化蜘蛛:
spider = MySpider(date='01-01-2015')

或者,您甚至可以完全避免解析日期,直接在第一次传递中使用datetime实例:

class MySpider(CrawlSpider):
    name = 'tw'
    allowed_domains = ['test.com']

    def __init__(self, *args, **kwargs):
        super(MySpider, self).__init__(*args, **kwargs) 

        dt = kwargs.get('dt')
        if not dt:
            raise ValueError('No date given')

        self.start_urls = ['http://test.com/{dt.year}-{dt.month}-{dt.day}'.format(dt=dt)]

spider = MySpider(dt=datetime(year=2014, month=01, day=01))

顺便提一下,你可以参考这篇回答作为如何从脚本中运行Scrapy的详细示例。


非常感谢您的解释!正如我所说,时间解析器是一个测试!还要感谢您提供的链接建议,现在您可以看到我的“解析”函数产生了“url”,我该如何获得它?(在运行爬取之后) - Mazdak
我使用了items,但是它引发了KeyError,似乎没有运行爬取!for url in item['url']: - Mazdak
@KasraAD 我认为你只需要使用yield item而不是yield item['url']。如果有帮助,请告诉我。 - alecxe
在我的爬虫中,我只是再次使用yield item,但出现了错误!我会编辑问题!我添加了我的脚本!希望这能有所帮助! - Mazdak
@KasraAD 有两件事情:1. 为什么你要在运行爬虫的脚本中实例化一个项目(我认为你不需要在这里这样做)。如果你想要对从爬虫返回的项目进行后处理,请在管道中完成。2. 你能否也展示一下 PoptopItem 类的定义。谢谢。 - alecxe
是的,我添加了它,实际上我是 scrapy 的新手!我之前没有使用过 pipline,但我在这里所需要的就是能够在我的脚本中获取 question.extract() - Mazdak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接