1+ from urllib .error import HTTPError
2+
13from requests import get
24from scrapy .http import TextResponse , XmlResponse
35
6+ from newsplease .config import CrawlerConfig
47from newsplease .crawler .spiders .newsplease_spider import NewspleaseSpider
58from newsplease .helper_classes .url_extractor import UrlExtractor
69
@@ -46,7 +49,7 @@ def __init__(self, helper, url, config, ignore_regex, *args, **kwargs):
4649 if config .section ("Crawler" ).get ('check_certificate' ) is not None
4750 else True )
4851
49- self .start_urls = [ self . helper . url_extractor . get_start_url (url )]
52+ self .start_urls = RssCrawler . _get_rss_start_urls (url = url , check_certificate = self . check_certificate )
5053
5154 super (RssCrawler , self ).__init__ (* args , ** kwargs )
5255
@@ -56,8 +59,10 @@ def parse(self, response):
5659
5760 :param obj response: The scrapy response
5861 """
62+ rss_url = UrlExtractor .get_rss_url (response )
63+ self .logger .info (f"Retrieving RSS articles from { rss_url } " )
5964 yield scrapy .Request (
60- UrlExtractor . get_rss_url ( response ) , callback = self .rss_parse
65+ rss_url , callback = self .rss_parse
6166 )
6267
6368 def rss_parse (self , response ):
@@ -100,6 +105,27 @@ def only_extracts_articles():
100105 """
101106 return True
102107
108+ @staticmethod
109+ def _get_rss_start_urls (url : str , check_certificate : bool = True ) -> list [str ]:
110+ config = CrawlerConfig .get_instance ()
111+ rss_patterns = config .section ("Crawler" ).get ("rss_parent_pages" , [])
112+
113+ valid_start_urls = []
114+ for pattern in rss_patterns :
115+ rss_url = "http://" + UrlExtractor .get_allowed_domain (url ) + '/' + pattern
116+ try :
117+ redirect_url = UrlExtractor .follow_redirects (url = rss_url , check_certificate = check_certificate )
118+
119+ # Check if a standard rss feed exists
120+ response = UrlExtractor .request_url (url = redirect_url , check_certificate = check_certificate ).read ()
121+ if response and re .search (re_rss , response .decode ("utf-8" )) is not None :
122+ valid_start_urls .append (rss_url )
123+ except HTTPError :
124+ # 404 for this start URL, do not raise an error
125+ pass
126+
127+ return valid_start_urls
128+
103129 @staticmethod
104130 def supports_site (url : str , check_certificate : bool = True ) -> bool :
105131 """
@@ -112,12 +138,7 @@ def supports_site(url: str, check_certificate: bool = True) -> bool:
112138 :return bool: Determines wether this crawler work on the given url
113139 """
114140
115- # Follow redirects
116- redirect_url = UrlExtractor .follow_redirects (url = url , check_certificate = check_certificate )
117-
118- # Check if a standard rss feed exists
119- response = UrlExtractor .request_url (url = redirect_url , check_certificate = check_certificate ).read ()
120- return re .search (re_rss , response .decode ("utf-8" )) is not None
141+ return len (RssCrawler ._get_rss_start_urls (url = url , check_certificate = check_certificate )) > 0
121142
122143 @staticmethod
123144 def has_urls_to_scan (url : str , check_certificate : bool = True ) -> bool :
@@ -128,19 +149,22 @@ def has_urls_to_scan(url: str, check_certificate: bool = True) -> bool:
128149 :param bool check_certificate:
129150 :return bool:
130151 """
131- redirect_url = UrlExtractor .follow_redirects (url = url , check_certificate = check_certificate )
152+ urls_to_scan = []
153+ for start_url in RssCrawler ._get_rss_start_urls (url = url , check_certificate = check_certificate ):
154+
155+ redirect_url = UrlExtractor .follow_redirects (url = start_url , check_certificate = check_certificate )
132156
133- response = get (url = redirect_url , verify = check_certificate )
134- scrapy_response = TextResponse (url = redirect_url , body = response .text .encode ())
157+ response = get (url = redirect_url , verify = check_certificate )
158+ scrapy_response = TextResponse (url = redirect_url , body = response .text .encode ())
135159
136- rss_url = UrlExtractor .get_rss_url (scrapy_response )
137- rss_content = get (url = rss_url , verify = check_certificate ).text
138- rss_response = XmlResponse (url = rss_url , body = rss_content , encoding = "utf-8" )
160+ rss_url = UrlExtractor .get_rss_url (scrapy_response )
161+ rss_content = get (url = rss_url , verify = check_certificate ).text
162+ rss_response = XmlResponse (url = rss_url , body = rss_content , encoding = "utf-8" )
139163
140- urls_to_scan = [
141- url
142- for item in rss_response .xpath ("//item" )
143- for url in item .xpath ("link/text()" ).extract ()
144- ]
164+ urls_to_scan = urls_to_scan + [
165+ url
166+ for item in rss_response .xpath ("//item" )
167+ for url in item .xpath ("link/text()" ).extract ()
168+ ]
145169
146170 return len (urls_to_scan ) > 0
0 commit comments