Паук Scrapy не возвращает данные об элементах - PullRequest
0 голосов
/ 29 января 2019

Мой сценарий scrapy, похоже, не следует ссылкам, что в итоге не приводит к извлечению данных из каждой из них (для передачи некоторого содержимого как scrapy items).

Я пытаюсь очистить много данных отновостной сайт.Мне удалось скопировать / написать паука, который, как я предполагал, должен прочитать ссылки из файла (я создал его с помощью другого скрипта), поместить их в список start_urls и начать переходить по этим ссылкам, чтобы извлечь некоторые данные, а затемпередайте его как items, а также - запишите данные каждого элемента в отдельный файл (последняя часть фактически относится к другому вопросу).

После запуска scrapy crawl PNS скрипт просматривает все ссылки с start_urls но больше ничего не делает - он следует ссылкам, прочитанным из списка start_urls (я получаю сообщение "GET link" в bash), но, похоже, не вводит их и не читает еще несколько ссылок, по которым нужно следовать и извлекать данные.

import scrapy
import re
from ProjectName.items import ProjectNameArticle

class ProjectNameSpider(scrapy.Spider):

    name = 'PNS'

    allowed_domains = ['www.project-domain.com']

    start_urls = []

    with open('start_urls.txt', 'r') as file:
        for line in file:
            start_urls.append(line.strip())

    def parse(self, response):
        for link in response.css('div.news-wrapper_ h3.b-item__title a').xpath('@href').extract():
            # extracted links look like this: "/document.html"
            link = "https://project-domain.com" + link
            yield scrapy.Request(link, callback=self.parse_news)

    def parse_news(self, response):

        data_dic = ProjectNameArticle() 

        data_dic['article_date'] =  response.css('div.article__date::text').extract_first().strip()
        data_dic['article_time'] =  response.css('span.article__time::text').extract_first().strip()
        data_dic['article_title'] = response.css('h3.article__title::text').extract_first().strip()
        news_text =  response.css('div.article__text').extract_first()
        news_text =  re.sub(r'(<script(\s|\S)*?<\/script>)|(<style(\s|\S)*?<\/style>)|(<!--(\s|\S)*?-->)|(<\/?(\s|\S)*?>)', '', news_text).strip()
        data_dic['article_text'] = news_text
        return data_dic

Ожидаемый результат:

  1. Скрипт открывает файл start_urls.txt, читает его строки (каждая строка содержит одну ссылку), помещает эти ссылки в список start_urls,
  2. Для каждой открытой ссылки паук извлекает более глубокие ссылки, по которым нужно следовать (это около 50-200 ссылок для каждой start_urls ссылки),
  3. Следующие ссылки являются основной целью, из которой я хочу извлечьконкретные данные: название статьи, дата, время, текст.
  4. Пока что не забудьте записать каждый элемент scrap в отдельный текстовый файл .txt.

Фактический результат:

  1. Запуск моего паука вызывает GET для каждой ссылки start_urls, проходит около 150000, не создает списокболее глубоких ссылок и не вводит их для извлечения каких-либо данных.

1 Ответ

0 голосов
/ 30 января 2019

Чувак, я давно пишу в Python Scrapy и ненавижу использовать start_urls

Вы можете просто использовать start_requests, который очень легко читается, а также очень прост в освоении для начинающих

class ProjectNameSpider(scrapy.Spider):

    name = 'PNS'

    allowed_domains = ['www.project-domain.com']

    def start_requests(self):

        with open('start_urls.txt', 'r') as file:
            for line in file:
                yield Request(line.strip(), 
                    callback=self.my_callback_func)

    def my_callback_func(self, response):
        for link in response.css('div.news-wrapper_ h3.b-item__title a').xpath('@href').extract():
            # extracted links look like this: "/document.html"
            link = "https://project-domain.com" + link
            yield scrapy.Request(link, callback=self.parse_news)

    def parse_news(self, response):

        data_dic = ProjectNameArticle() 

        data_dic['article_date'] =  response.css('div.article__date::text').extract_first().strip()
        data_dic['article_time'] =  response.css('span.article__time::text').extract_first().strip()
        data_dic['article_title'] = response.css('h3.article__title::text').extract_first().strip()
        news_text =  response.css('div.article__text').extract_first()
        news_text =  re.sub(r'(<script(\s|\S)*?<\/script>)|(<style(\s|\S)*?<\/style>)|(<!--(\s|\S)*?-->)|(<\/?(\s|\S)*?>)', '', news_text).strip()
        data_dic['article_text'] = news_text
        return data_dic

Я также никогда не использовал Item класс и считаю его тоже бесполезным

Вы можете просто иметь data_dic = {} вместо data_dic = ProjectNameArticle()

...