Обход ссылок с использованием Scrapy

#python #scrapy

#питон #scrapy

Вопрос:

У меня странная проблема, связанная с Scrapy. Я следовал руководству по обходу ссылок, но по какой-то причине ничего не происходит.

 import scrapy
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
from bs4 import BeautifulSoup
import pandas as pd
from time import strftime

class Covid_Crawler(scrapy.Spider):
     name = "Covid_Crawler"
     allowed_domains = ['worldometers.info/coronavirus/']
     start_urls = ['https://www.worldometers.info/coronavirus/countries-where-coronavirus-has-spread/']

 def parse(self, response):
    count = 0
    soup = BeautifulSoup(response.text, "lxml")
    try:
        covid_table = soup.find('table')
        df = pd.read_html(str(covid_table))[0]
        print(df)
        df.to_csv("CovidFile.csv",index=False)                        

    except:
        print("Table not found")

    NEXT_PAGE_SELECTOR = 'a::attr(href)'
    next_page = response.css(NEXT_PAGE_SELECTOR).getall()
    if next_page is not None:
        yield response.follow(next_page, callback=self.parse)
 

По какой-то причине, когда я пытаюсь запустить этот паук, он отлично захватывает таблицу с первой страницы. Но он не хочет переходить к другим ссылкам. Когда я запускаю его, я получаю что-то вроде этого.

  2020-12-12 20:45:15 [scrapy.core.engine] DEBUG: Crawled (200) <GET 
 https://www.worldometers.info/coronavirus/countries-where-coronavirus-has-spread/> (referer: None)
 2020-12-12 20:45:15 [numexpr.utils] INFO: NumExpr defaulting to 6 threads.
               Country     Cases  Deaths             Region
 0       United States  16549366  305082      North America
 1               India   9857380  143055               Asia
 2              Brazil   6880595  181143      South America
 3              Russia   2625848   46453             Europe
 4              France   2365319   57761             Europe
 ..                ...       ...     ...                ...
 214        MS Zaandam         9       2                NaN
 215  Marshall Islands         4       0  Australia/Oceania
 216   Wallis amp; Futuna         3       0  Australia/Oceania
 217             Samoa         2       0  Australia/Oceania
 218           Vanuatu         1       0  Australia/Oceania

 [219 rows x 4 columns]
 2020-12-12 20:45:15 [scrapy.core.scraper] ERROR: Spider error processing <GET 
 https://www.worldometers.info/coronavirus/countries-where-coronavirus-has-spread/> (referer: None)
 Traceback (most recent call last):
 File "C:UsersZach Kunzanaconda3libsite-packagesscrapyutilsdefer.py", line 120, in iter_errback
yield next(it)
 File "C:UsersZach Kunzanaconda3libsite-packagesscrapyutilspython.py", line 353, in __next__
return next(self.data)
 File "C:UsersZach Kunzanaconda3libsite-packagesscrapyutilspython.py", line 353, in __next__
return next(self.data)
 File "C:UsersZach Kunzanaconda3libsite-packagesscrapycorespidermw.py", line 62, in _evaluate_iterable
for r in iterable:
 File "C:UsersZach Kunzanaconda3libsite-packagesscrapyspidermiddlewaresoffsite.py", line 29, in process_spider_output
for x in result:
 File "C:UsersZach Kunzanaconda3libsite-packagesscrapycorespidermw.py", line 62, in _evaluate_iterable
for r in iterable:
 File "C:UsersZach Kunzanaconda3libsite-packagesscrapyspidermiddlewaresreferer.py", line 340, in <genexpr>
return (_set_referer(r) for r in result or ())
 File "C:UsersZach Kunzanaconda3libsite-packagesscrapycorespidermw.py", line 62, in _evaluate_iterable
for r in iterable:
 File "C:UsersZach Kunzanaconda3libsite-packagesscrapyspidermiddlewaresurllength.py", line 37, in <genexpr>
return (r for r in result or () if _filter(r))
 File "C:UsersZach Kunzanaconda3libsite-packagesscrapycorespidermw.py", line 62, in _evaluate_iterable
for r in iterable:
 File "C:UsersZach Kunzanaconda3libsite-packagesscrapyspidermiddlewaresdepth.py", line 58, in <genexpr>
return (r for r in result or () if _filter(r))
 File "C:UsersZach Kunzanaconda3libsite-packagesscrapycorespidermw.py", line 62, in _evaluate_iterable
for r in iterable:
 File "C:UsersZach KunzDocumentsCrawler_TestCovid_CrawlerCovid_CrawlerspidersCrawler_spider.py", line 84, in parse
yield response.follow(next_page, callback=self.parse)
 File "C:UsersZach Kunzanaconda3libsite-packagesscrapyhttpresponsetext.py", line 169, in follow
return super().follow(
 File "C:UsersZach Kunzanaconda3libsite-packagesscrapyhttpresponse__init__.py", line 143, in follow
url = self.urljoin(url)
 File "C:UsersZach Kunzanaconda3libsite-packagesscrapyhttpresponsetext.py", line 102, in urljoin
return urljoin(get_base_url(self), url)
 File "C:UsersZach Kunzanaconda3liburllibparse.py", line 512, in urljoin
base, url, _coerce_result = _coerce_args(base, url)
 File "C:UsersZach Kunzanaconda3liburllibparse.py", line 121, in _coerce_args
raise TypeError("Cannot mix str and non-str arguments")
 TypeError: Cannot mix str and non-str arguments
 2020-12-12 20:45:15 [scrapy.core.engine] INFO: Closing spider (finished)
 

И используя оболочку scrapy, чтобы проверить, получает ли она ссылки, я получаю это

  In [6]: response.css('a::attr(href)').getall()
 Out[6]:
 ['/',
  '/coronavirus/',
  '/population/',
  '/coronavirus/',
  '/coronavirus/',
  '/coronavirus/coronavirus-cases/',
  '/coronavirus/worldwide-graphs/',
  '/coronavirus/#countries',
  '/coronavirus/coronavirus-death-rate/',
  '/coronavirus/coronavirus-incubation-period/',
  '/coronavirus/coronavirus-age-sex-demographics/',
  '/coronavirus/coronavirus-symptoms/',
  '/coronavirus/',
  '/coronavirus/coronavirus-death-toll/',
  '/coronavirus/#countries',
  '/coronavirus/',
  '/coronavirus/coronavirus-cases/',
  '/coronavirus/coronavirus-death-toll/',
  '/coronavirus/coronavirus-death-rate/',
  '/coronavirus/coronavirus-incubation-period/',
  '/coronavirus/coronavirus-age-sex-demographics/',
  '/coronavirus/coronavirus-symptoms/',
  '/coronavirus/countries-where-coronavirus-has-spread/',
  '/coronavirus/#countries',
  '/',
  '/about/',
  '/faq/',
  '/languages/',
  '/contact/',
  '/newsletter-subscribe/',
   'https://twitter.com/Worldometers',
   'https://www.facebook.com/Worldometers.info',
   '/disclaimer/']
 

Любая помощь или понимание будут высоко оценены. И если вы готовы помочь с другой проблемой, я ищу решение для хранения всех диаграмм, которые я собираю, в нескольких файлах csv или xlsx. Спасибо!

Ответ №1:

response.follow() не могу работать с а list . Вам нужно указать один строковый аргумент:

 next_pages = response.css(NEXT_PAGE_SELECTOR).getall()
for next_page in next_pages:
    if next_page is not None:
        yield response.follow(next_page, callback=self.parse)
 

Комментарии:

1. Это действительно работает, спасибо! Единственная проблема заключается в том, что, похоже, он только захватывает ссылки с помощью http, в котором нет того, что я хочу. Как это будет работать для ссылок, которые просто имеют расширение к нему?

2. Неважно, я понял это. Спасибо за помощь!

Ответ №2:

Вы могли бы использовать yield from response.follow_all(next_pages) which, который делал бы то же самое, что и то, что опубликовал gangabass.