Python `如何在scrapy中使用回调链

Python `如何在scrapy中使用回调链,python,firefox,selenium,scrapy,screen-scraping,Python,Firefox,Selenium,Scrapy,Screen Scraping,我正在尝试使用scrapy和SeleniumWebDriver构建一个爬虫程序。我试图在parse()中获取一组url,并将其传递给回调函数parse\u url(),该函数再次获取另一组url,并将其传递给parse\u data() 对parse_url的第一次回调有效,但对parse_data的第二次回调给出了一个AssertionError i、 e如果我运行时没有parse_data,它会打印URL列表。但是如果我包括它,我会得到一个断言错误 我有类似的东西 class mySpide

我正在尝试使用scrapy和SeleniumWebDriver构建一个爬虫程序。我试图在
parse()
中获取一组url,并将其传递给回调函数
parse\u url()
,该函数再次获取另一组url,并将其传递给
parse\u data()

parse_url
的第一次回调有效,但对
parse_data
的第二次回调给出了一个
AssertionError

i、 e如果我运行时没有
parse_data
,它会打印URL列表。但是如果我包括它,我会得到一个断言错误

我有类似的东西

class mySpider(scrapy.Spider):
    name = "mySpider"
    allowed_domains = ["example.com"]
    start_urls = [
        "http://www.example.com/url",
    ]

    def parse(self, response):
        driver = webdriver.firefox()
    driver.get(response.url)
    urls = get_urls(driver.page_source) # get_url returns a list
        yield scrapy.Request(urls, callback=self.parse_url(urls, driver))

    def parse_url(self, url, driver):
        url_list = []
    for i in urls:
    driver.get(i)
    url_list.append( get_urls(driver.pagesource)) # gets some more urls 
    yeild scrapy.Request(urls, callback=self.parse_data(url_list, driver))

    def parse_data(self, url_list, driver):
        data = get_data(driver.pagesource)
这是回溯

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/scrapy/utils/defer.py", line 45, in mustbe_deferred
    result = f(*args, **kw)
  File "/usr/local/lib/python2.7/dist-packages/scrapy/core/spidermw.py", line 48, in process_spider_input
    return scrape_func(response, request, spider)
  File "/usr/local/lib/python2.7/dist-packages/scrapy/core/scraper.py", line 145, in call_spider
    dfd.addCallbacks(request.callback or spider.parse, request.errback)
  File "/usr/local/lib/python2.7/dist-packages/twisted/internet/defer.py", line 299, in addCallbacks
    assert callable(callback)
AssertionError

有两个问题:

  • 您没有将函数传递给请求。您正在将函数的返回值传递给请求

  • 请求的回调函数必须具有签名(self、response)

  • 动态内容的解决方案如下:

    它将消除将驱动程序传递到函数的需要

    所以当你答应你的要求时,应该是这样的

    scrapy.Request(urls, callback=self.parse_url)
    
    如果你真的想在函数中包含驱动程序,请阅读闭包

    编辑:这是一个闭包解决方案,但我认为你应该使用我共享的链接,因为GHajba指出了原因

       def parse_data(self, url_list, driver):
            def encapsulated(spider, response)
                data = get_data(driver.pagesource)
                .....
                .....
                yield item
        return encapsulated
    
    那么你的请求看起来像

    yield scrapy.request(url, callback=self.parse_data(url_list, driver)
    

    另一方面:我觉得你用Selenium做了很多事情,这也可以用Scrapy来做:从站点中提取URL(目前你加载站点两次:一次用Scrapy,然后用Selenium)。该网页具有动态内容。在实际代码中,我必须向下滚动并让元素加载。谢谢你!是我一直在寻找的,但我不知道。