scrapy follow next_page for each single article

Viewed 54

I would like to get news content on the next page but, it's not working. I got only first page content. The structure of the website are:

  1. index news articles
    • single news article
      • next_page in single news article (if any)

The code that I use:

import scrapy
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
from datetime import datetime
from datetime import timedelta, date
from bs4 import BeautifulSoup
import json
from json.decoder import JSONDecodeError

class CnnindonesianewsSpider(CrawlSpider):
    name = 'cnnindonesianews'
    allowed_domains = ['https://www.cnnindonesia.com/indeks']
   
    def daterange(start_date, end_date):
        for n in range(int((end_date - start_date).days)):
            yield start_date + timedelta(n)

    start_date = date(2021, 8, 6)
    end_date = date(2021, 8, 7)
    start_urls = [] 
    start_url='https://www.cnnindonesia.com/indeks'
   
    custom_settings = {
        'DEPTH_LIMIT': 2
    }
    
    n=2
    for single_date in daterange(start_date, end_date):
        for i in range (3,4):
            start_urls.append(single_date.strftime(start_url+str("?date=")+"%Y/%m/%d")+str("&p=")+str(i)+str("&kanal=2"))
            def parse(self, response):
                for links in response.css('div.list.media_rows.middle > article > a::attr(href)').extract():
                    if links is not None:
                        print(links)
                        links = response.urljoin(links)  
                        yield scrapy.Request(links, callback=self.parse_dir_contents, dont_filter=True)
            
                    
            #get all detail data from scraped page by visiting link/url        
            def parse_dir_contents(self, response):
                for quote in response.css('html'):
                
                    microdata_content = response.xpath('//script[@type="application/ld+json"][2]/text()').extract_first()
           
                    if  microdata_content is not None:
                        microdata = json.loads(microdata_content)   
                        author = microdata["author"]["name"]
                        daten = microdata["datePublished"]
                        modif = microdata["dateModified"]
                        publisher = microdata["publisher"]["name"]
                    else:
                        author = quote.css("meta[name='author']::attr(content)").extract_first()
                        daten = quote.css("meta[itemprop='article:published_time']::attr(content)").extract_first()
                        publisher = "CNN Indonesia"
                        
                    yield {
                              'url': quote.css("meta[property='og:url']::attr(content)").get(),
                              'title' : quote.css("meta[property='og:title']::attr(content)").get(),
                              'datePublished' : quote.css('div.author-time::text').get(default=daten),
                              'dateModified' : quote.css('div.author-time::text').get(default=modif),
                              'author' : quote.css('div.authour-name > strong::text').get(default=author),
                              'content' : quote.css('div.detail_text > p::text').getall(),
                              'content_tag' : quote.css("meta[name=keywords]::attr(content)").get()  
                    }
                    
                    # follow next page links
                    next_page = response.css('.text_right > a:nth-child(2)::attr(href)').extract()
                    if next_page:
                        yield scrapy.Request(response.urljoin(next_page))

And I want also to store the content data that I get from first page and second page into the "content" field.

following the example of single page that has "next_page" inside:

https://www.cnnindonesia.com/hiburan/20210806163452-220-677425/5-rekomendasi-film-akhir-pekan-the-suicide-squad

Thank you for any help

1 Answers

Try
next_page = response.css('.text_right > a:nth-child(2)::attr(href)').extract_first()

extract() is returning a list and urljoin can't concatenate str and list

Related