python - example - Scrapy CrawlSpider para contenido AJAX
scrapy python install (1)
Estoy intentando rastrear un sitio para artículos de noticias. Mi start_url contiene:
(1) enlaces a cada artículo: http://example.com/symbol/TSLA
y
(2) un botón "Más" que realiza una llamada AJAX que carga dinámicamente más artículos dentro del mismo start_url: http://example.com/account/ajax_headlines_content?type=in_focus_articles&page=0&slugs=tsla&is_symbol_page=true
Un parámetro para la llamada AJAX es "página", que se incrementa cada vez que se hace clic en el botón "Más". Por ejemplo, al hacer clic en "Más" una vez, se cargarán n artículos adicionales y se actualizará el parámetro de página en el botón "Más" en el evento Click, para que la próxima vez que se haga clic en "Más", se cargarán dos "artículos" (asumiendo " la página "0 se cargó inicialmente, y la" página "1 se cargó en el primer clic).
Para cada "página" me gustaría raspar los contenidos de cada artículo usando las Reglas, pero no sé cuántas "páginas" hay y no quiero elegir alguna m arbitraria (por ejemplo, 10k). Parece que no puedo entender cómo configurar esto.
A partir de esta pregunta, Scrapy Crawl URLs en orden , intenté crear una lista de URL de posibles URL, pero no puedo determinar cómo y dónde enviar una nueva URL desde el grupo después de analizar la URL anterior y asegurar que contenga enlaces de noticias. para un CrawlSpider. Mis reglas envían respuestas a una devolución de llamada parse_items, donde se analizan los contenidos del artículo.
¿Hay alguna manera de observar los contenidos de la página de enlaces (similar al ejemplo de BaseSpider) antes de aplicar Rules y llamar a parse_items para saber cuándo dejar de rastrear?
Código simplificado (eliminé varios de los campos que estoy analizando para mayor claridad):
class ExampleSite(CrawlSpider):
name = "so"
download_delay = 2
more_pages = True
current_page = 0
allowed_domains = [''example.com'']
start_urls = [''http://example.com/account/ajax_headlines_content?type=in_focus_articles&page=0''+
''&slugs=tsla&is_symbol_page=true'']
##could also use
##start_urls = [''http://example.com/symbol/tsla'']
ajax_urls = []
for i in range(1,1000):
ajax_urls.append(''http://example.com/account/ajax_headlines_content?type=in_focus_articles&page=''+str(i)+
''&slugs=tsla&is_symbol_page=true'')
rules = (
Rule(SgmlLinkExtractor(allow=(''/symbol/tsla'', ))),
Rule(SgmlLinkExtractor(allow=(''/news-article.*tesla.*'', ''/article.*tesla.*'', )), callback=''parse_item'')
)
##need something like this??
##override parse?
## if response.body == ''no results'':
## self.more_pages = False
## ##stop crawler??
## else:
## self.current_page = self.current_page + 1
## yield Request(self.ajax_urls[self.current_page], callback=self.parse_start_url)
def parse_item(self, response):
self.log("Scraping: %s" % response.url, level=log.INFO)
hxs = Selector(response)
item = NewsItem()
item[''url''] = response.url
item[''source''] = ''example''
item[''title''] = hxs.xpath(''//title/text()'')
item[''date''] = hxs.xpath(''//div[@class="article_info_pos"]/span/text()'')
yield item
Crawl araña puede ser demasiado limitado para sus propósitos aquí. Si necesita mucha lógica, generalmente es mejor heredar de Spider.
Scrapy proporciona una excepción de CloseSpider que se puede generar cuando necesita detener el análisis bajo ciertas condiciones. La página que está rastreando muestra el mensaje "No hay artículos de Enfoque en sus existencias", cuando supera la página máxima, puede verificar este mensaje y detener la iteración cuando aparece este mensaje.
En tu caso, puedes ir con algo como esto:
from scrapy.spider import Spider
from scrapy.http import Request
from scrapy.exceptions import CloseSpider
class ExampleSite(Spider):
name = "so"
download_delay = 0.1
more_pages = True
next_page = 1
start_urls = [''http://example.com/account/ajax_headlines_content?type=in_focus_articles&page=0''+
''&slugs=tsla&is_symbol_page=true'']
allowed_domains = [''example.com'']
def create_ajax_request(self, page_number):
"""
Helper function to create ajax request for next page.
"""
ajax_template = ''http://example.com/account/ajax_headlines_content?type=in_focus_articles&page={pagenum}&slugs=tsla&is_symbol_page=true''
url = ajax_template.format(pagenum=page_number)
return Request(url, callback=self.parse)
def parse(self, response):
"""
Parsing of each page.
"""
if "There are no Focus articles on your stocks." in response.body:
self.log("About to close spider", log.WARNING)
raise CloseSpider(reason="no more pages to parse")
# there is some content extract links to articles
sel = Selector(response)
links_xpath = "//div[@class=''symbol_article'']/a/@href"
links = sel.xpath(links_xpath).extract()
for link in links:
url = urljoin(response.url, link)
# follow link to article
# commented out to see how pagination works
#yield Request(url, callback=self.parse_item)
# generate request for next page
self.next_page += 1
yield self.create_ajax_request(self.next_page)
def parse_item(self, response):
"""
Parsing of each article page.
"""
self.log("Scraping: %s" % response.url, level=log.INFO)
hxs = Selector(response)
item = NewsItem()
item[''url''] = response.url
item[''source''] = ''example''
item[''title''] = hxs.xpath(''//title/text()'')
item[''date''] = hxs.xpath(''//div[@class="article_info_pos"]/span/text()'')
yield item