Uso de Scrapy para rastrear las URL en la página web
-
25-10-2019 - |
Pregunta
Estoy usando Scrapy para extraer datos de ciertos sitios web. El problema es que mi araña solo puede rastrear la página web de inicial inicio_urls, no puede rastrear las URL en la página web. Copié la misma araña exactamente:
from scrapy.spider import BaseSpider
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
from scrapy.selector import HtmlXPathSelector
from scrapy.http import Request
from scrapy.utils.response import get_base_url
from scrapy.utils.url import urljoin_rfc
from nextlink.items import NextlinkItem
class Nextlink_Spider(BaseSpider):
name = "Nextlink"
allowed_domains = ["Nextlink"]
start_urls = ["http://www.dmoz.org/Computers/Programming/Languages/Python/Books/"]
def parse(self, response):
hxs = HtmlXPathSelector(response)
sites = hxs.select('//body/div[2]/div[3]/div/ul/li[2]/a/@href')
for site in sites:
relative_url = site.extract()
url = self._urljoin(response,relative_url)
yield Request(url, callback = self.parsetext)
def parsetext(self, response):
log = open("log.txt", "a")
log.write("test if the parsetext is called")
hxs = HtmlXPathSelector(response)
items = []
texts = hxs.select('//div').extract()
for text in texts:
item = NextlinkItem()
item['text'] = text
items.append(item)
log = open("log.txt", "a")
log.write(text)
return items
def _urljoin(self, response, url):
"""Helper to convert relative urls to absolute"""
return urljoin_rfc(response.url, url, response.encoding)
Utilizo log.txt para probar si se llama el texto parsette. Sin embargo, después de ejecutar mi araña, no hay nada en log.txt.
Solución
Mira aquí:
PERMINADO_DOMINAINS
Una lista opcional de cadenas que contienen dominios que esta araña puede gatear. Las solicitudes de URL que no pertenecen a los nombres de dominio especificados en esta lista no se seguirán si OffSitemIddleware está habilitado.
Entonces, siempre y cuando no active el SitemidDleware en su configuración, no importa y puede irse allowed_domains
completamente fuera.
Verifique el settings.py si el ofsitemIDdleware está activado o no. No debe activarse si desea permitir que su araña se arrastre en cualquier dominio.
Otros consejos
Creo que el problema es que no le dijiste a Scrapy que siguiera cada URL rastreada. Para mi propio blog, implementé un Crawlspider que utiliza reglas basadas en LinkExtractor para extraer todos los enlaces relevantes de mis páginas de blog:
# -*- coding: utf-8 -*-
'''
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @author Marcel Lange <info@ask-sheldon.com>
* @package ScrapyCrawler
'''
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
import Crawler.settings
from Crawler.items import PageCrawlerItem
class SheldonSpider(CrawlSpider):
name = Crawler.settings.CRAWLER_NAME
allowed_domains = Crawler.settings.CRAWLER_DOMAINS
start_urls = Crawler.settings.CRAWLER_START_URLS
rules = (
Rule(
LinkExtractor(
allow_domains=Crawler.settings.CRAWLER_DOMAINS,
allow=Crawler.settings.CRAWLER_ALLOW_REGEX,
deny=Crawler.settings.CRAWLER_DENY_REGEX,
restrict_css=Crawler.settings.CSS_SELECTORS,
canonicalize=True,
unique=True
),
follow=True,
callback='parse_item',
process_links='filter_links'
),
)
# Filter links with the nofollow attribute
def filter_links(self, links):
return_links = list()
if links:
for link in links:
if not link.nofollow:
return_links.append(link)
else:
self.logger.debug('Dropped link %s because nofollow attribute was set.' % link.url)
return return_links
def parse_item(self, response):
# self.logger.info('Parsed URL: %s with STATUS %s', response.url, response.status)
item = PageCrawlerItem()
item['status'] = response.status
item['title'] = response.xpath('//title/text()')[0].extract()
item['url'] = response.url
item['headers'] = response.headers
return item
En https://www.ask-sheldon.com/build-a-website-crawler-using-scrapy-framework/ Describí detallado cómo he implementado un rastreador de sitios web para calentar mi caché de páginas completas de WordPress.
Mi suposición sería esta línea:
allowed_domains = ["Nextlink"]
Este no es un dominio como dominio.tld, por lo que rechazaría cualquier enlace. Si toma el ejemplo de la documentación: allowed_domains = ["dmoz.org"]