25

我已经使用scrapy编写了一个工作爬虫,
现在我想通过一个Django webapp来控制它,也就是说:

  • 设置 1 个或多个start_urls
  • 设置 1 个或多个allowed_domains
  • 设定settings
  • 启动蜘蛛
  • 停止/暂停/恢复蜘蛛
  • 在运行时检索一些统计信息
  • 蜘蛛完成后检索一些统计信息。

一开始我以为scrapyd就是为此而生的,但是在阅读了文档之后,它似乎更像是一个能够管理“打包蜘蛛”的守护进程,也就是“scrapy Eggs”;并且所有设置(start_urls, allowed_domains, settings)仍然必须在“scrapy egg”本身中进行硬编码;所以它看起来不像是我的问题的解决方案,除非我错过了什么。

我也看了这个问题:How to give URL to scrapy for crawling? ; 但是提供多个 url 的最佳答案被作者 himeslf 限定为“丑陋的 hack”,涉及一些 python 子进程和复杂的 shell 处理,所以我认为在这里找不到解决方案。此外,它可能适用于start_urls,但似乎不允许allowed_domainssettings

然后我看了一下scrapy webservices:这似乎是检索统计数据的好方法。但是,它仍然需要一个正在运行的蜘蛛,并且没有任何改变的线索settings

关于这个主题有几个问题,似乎没有一个令人满意:

我知道scrapy用于生产环境;并且像scrapyd这样的工具表明确实有一些方法可以处理这些要求(我无法想象scrapyd正在处理的scrapy鸡蛋是手工生成的!)

非常感谢你的帮助。

4

4 回答 4

10

一开始我以为scrapyd就是为此而生的,但是在阅读了文档之后,它似乎更像是一个能够管理“打包蜘蛛”的守护进程,也就是“scrapy Eggs”;并且所有设置(start_urls、allowed_domains、settings)仍然必须在“scrapy egg”本身中硬编码;所以它看起来不像是我的问题的解决方案,除非我错过了什么。

我不同意上面的说法,start_urls 不需要硬编码,它们可以动态传递给类,你应该可以像这样将它作为参数传递

http://localhost:6800/schedule.json -d project=myproject -d spider=somespider -d setting=DOWNLOAD_DELAY=2 -d arg1=val1

或者您应该能够从数据库或文件中检索 URL。我从这样的数据库中得到它

class WikipediaSpider(BaseSpider):
    name = 'wikipedia'
    allowed_domains = ['wikipedia.com']
    start_urls = []

    def __init__(self, name=None, url=None, **kwargs):
        item = MovieItem()
        item['spider'] = self.name
        # You can pass a specific url to retrieve 
        if url:
            if name is not None:
                self.name = name
            elif not getattr(self, 'name', None):
                raise ValueError("%s must have a name" % type(self).__name__)
            self.__dict__.update(kwargs)
            self.start_urls = [url]
        else:
            # If there is no specific URL get it from Database
            wikiliks = # < -- CODE TO RETRIEVE THE LINKS FROM DB -->
            if wikiliks == None:
                print "**************************************"
                print "No Links to Query"
                print "**************************************"
                return None

            for link in wikiliks:
                # SOME PROCESSING ON THE LINK GOES HERE
                self.start_urls.append(urllib.unquote_plus(link[0]))

    def parse(self, response):
        hxs = HtmlXPathSelector(response)
        # Remaining parse code goes here
于 2013-06-15T03:47:20.217 回答
8

为了以编程方式更改设置并从应用程序中运行刮板,这就是我得到的:

from scrapy.crawler import CrawlerProcess
from myproject.spiders import MySpider
from scrapy.utils.project import get_project_settings

os.environ['SCRAPY_SETTINGS_MODULE'] = 'myproject.my_settings_module'
scrapy_settings = get_project_settings()
scrapy_settings.set('CUSTOM_PARAM', custom_vaule)
scrapy_settings.set('ITEM_PIPELINES', {})  # don't write jsons or anything like that
scrapy_settings.set('DOWNLOADER_MIDDLEWARES', {
   'myproject.middlewares.SomeMiddleware': 100,
})
process = CrawlerProcess(scrapy_settings)
process.crawl(MySpider, start_urls=start_urls)
process.start()
于 2016-02-04T21:22:38.080 回答
3

这其实很简单!

from mypackage.spiders import MySpider
from scrapy.crawler import CrawlerProcess

results = []

class MyPipeline(object):
    """ A custom pipeline that stores scrape results in 'results'"""
    def process_item(self, item, spider):
        results.append(dict(item))

process = CrawlerProcess({
    # An example of a custom setting
    'USER_AGENT': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)',  
    'ITEM_PIPELINES': {'__main__.MyPipeline': 1},   # Hooking in our custom pipline above
})

start_urls=[
    'http://example.com/page1', 
    'http://example.com/page2',
]
process.crawl(MySpider, start_urls=start_urls)
process.start() # the script will block here until the crawling is finished

# Do something with the results
print results
于 2015-09-23T23:25:13.250 回答
0

我认为你需要看看这个

http://django-dynamic-scraper.readthedocs.org/en/latest/

这有点类似于你想要的。它还使用了任务调度的芹菜。您可以查看代码以了解他在做什么。我认为如果你修改他的代码来做你想做的事情会很容易

它还有关于如何使用 django 设置界面的好文档

于 2013-01-25T05:17:11.020 回答