Q: Scrapy - Can not do multiple callbacks I am having problems going through multiple pages. Here is my class for scrapy code called quotes.
class quotes(scrapy.Spider):
    name = 'quotes'
    start_urls = ['http://books.toscrape.com/?']

def parse(self, response):
    all_links = response.css('.nav-list ul li')
    for links in all_links:
        link = links.css('a::attr(href)').get()
        yield response.follow(link, callback = self.books_detail)

def books_detail(self, response):
    yas = {
    'title':[],
    'price':[],
    'availability':[],
    'category':[]
    }
    yas['category'].append(response.css('h1::text').extract())
    all_divs = response.css('.col-lg-3')
    for div in all_divs:
        link = div.css('.product_pod a::attr(href)').get()
        title = response.follow(link, callback = self.get_title)
        
        yas['price'].append(div.css('.price_color::text').extract())
        yas['availability'].append(div.css('.availability::text')[1].extract())
    yield yas


def get_title(self,response):   
    print('testing')
    title = response.css('h1::text').extract()
    yield {"title":title}

So I use a response.follow to goto function books_details and in that function, I again call response.follow to call get_title. I get the 'title' from get_title and the rest of the details from the main page.
I can scrape the information just fine from the books_details function and I can get the link of the title page just fine as well from the code line.
link = div.css('.product_pod a::attr(href)').get()

But using the response.follow I can not go to the get_title function.
Any help would be appreciated. Thanks.

A: You should yield request, not run it directly, and use meta= to send data to next parser
yield response.follow(link, callback=self.get_title, meta={'item': yas})

and in next parser you can get it 
yas = response.meta['item']

and then you can add new values and yield all data
yas["title"] = response.css('h1::text').extract()

yield yas


See other example in Scrapy yeild items from multiple requests
Doc: Request and Response, Request.meta special keys

Minimal working code which you can put in one file and run as normal script (python script.py) without creating project.
There are other changes. 
You shouldn't put all books to one list but yield every book separatelly. Scrapy will keep all results and when you use option to save in csv then it will save all results.
For every book you should create new dictionary. If you use the same dictionary many time then it will ovewrite data and you may get many result with the same data.
import scrapy

class QuotesSpider(scrapy.Spider):

    name = 'quotes'

    start_urls = ['http://books.toscrape.com/']

    def parse(self, response):
        all_links = response.css('.nav-list ul li')
        for links in all_links:
            link = links.css('a::attr(href)').get()
            yield response.follow(link, callback=self.books_detail)


    def books_detail(self, response):

        all_divs = response.css('.col-lg-3')

        for div in all_divs:
            # every book in separated dictionary and it has to be new dictionary - because it could overwrite old data
            book = {
                'category': response.css('h1::text').extract(),
                'price': div.css('.price_color::text').extract()[0].strip(),
                'availability': div.css('.availability::text')[1].extract().strip(),
            }

            link = div.css('.product_pod a::attr(href)').get()
            yield response.follow(link, callback=self.get_title, meta={'item': book})


    def get_title(self, response):
        book = response.meta['item']

        print('testing:', response.url)

        book["title"] = response.css('h1::text').extract()[0].strip() 

        yield book

# --- run without project and save in `output.csv` ---

from scrapy.crawler import CrawlerProcess

c = CrawlerProcess({
    'USER_AGENT': 'Mozilla/5.0',
    # save in file CSV, JSON or XML
    'FEED_FORMAT': 'csv',     # csv, json, xml
    'FEED_URI': 'output.csv', #
})

c.crawl(QuotesSpider)
c.start()

