Очистка "старых" страниц с помощью scrapy, правил и экстракторов ссылок

Я работал над проектом со скрапом. С помощью этого прекрасного сообщества мне удалось почистить первую страницу этого сайта: http://www.rotoworld.com/playernews/nfl/football-player-news?ls=roto%3Anfl%3Agnav. Я также пытаюсь собрать информацию со "старых" страниц. Я исследовал "crawlspider", правила и экстракторы ссылок, и полагал, что у меня был правильный код. Я хочу, чтобы паук выполнил тот же цикл на последующих страницах. К сожалению, в тот момент, когда я запускаю его, он просто выплевывает первую страницу и не переходит на "старые" страницы.

Я не совсем уверен, что мне нужно изменить, и был бы очень признателен за помощь. Есть посты вплоть до февраля 2004 года... Я новичок в области интеллектуального анализа данных, и не уверен, является ли это реалистичной целью, чтобы быть в состоянии очистить каждый пост. Если это так, я хотел бы, хотя. Пожалуйста, любая помощь приветствуется. Спасибо!

import scrapy
from scrapy.contrib.spiders import CrawlSpider,Rule
from scrapy.contrib.linkextractors import LinkExtractor



class Roto_News_Spider2(crawlspider):
    name = "RotoPlayerNews"

    start_urls = [
        'http://www.rotoworld.com/playernews/nfl/football/',
    ]

    Rules = (Rule(LinkExtractor(allow=(), restrict_xpaths=('//input[@id="cp1_ctl00_btnNavigate1"]',)), callback="parse_page", follow= True),)


    def parse(self, response):
        for item in response.xpath("//div[@class='pb']"):
            player = item.xpath(".//div[@class='player']/a/text()").extract_first()
            position= item.xpath(".//div[@class='player']/text()").extract()[0].replace("-","").strip()
            team = item.xpath(".//div[@class='player']/a/text()").extract()[1].strip()
            report = item.xpath(".//div[@class='report']/p/text()").extract_first()
            date = item.xpath(".//div[@class='date']/text()").extract_first() + " 2018"
            impact = item.xpath(".//div[@class='impact']/text()").extract_first().strip()
            source = item.xpath(".//div[@class='source']/a/text()").extract_first()
            yield {"Player": player,"Position": position, "Team": team,"Report":report,"Impact":impact,"Date":date,"Source":source}

3 ответа

Решение

Если вы намереваетесь получить данные, проходящие через несколько страниц, вам не нужно идти на копейки. Если вы все еще хотите иметь какое-либо решение, связанное с терапией, тогда я предлагаю вам выбрать всплеск для обработки нумерации страниц.

Я бы сделал что-то вроде ниже, чтобы получить предметы (при условии, что вы уже установили селен на свою машину):

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()
driver.get("http://www.rotoworld.com/playernews/nfl/football/")
wait = WebDriverWait(driver, 10)

while True:
    for item in wait.until(EC.presence_of_all_elements_located((By.XPATH,"//div[@class='pb']"))):
        player = item.find_element_by_xpath(".//div[@class='player']/a").text
        player = player.encode() #it should handle the encoding issue; I'm not totally sure, though
        print(player)

    try:
        idate = wait.until(EC.presence_of_element_located((By.XPATH, "//div[@class='date']"))).text
        if "Jun 9" in idate: #put here any date you wanna go back to (last limit: where the scraper will stop)
            break
        wait.until(EC.presence_of_element_located((By.XPATH, "//input[@id='cp1_ctl00_btnNavigate1']"))).click()
        wait.until(EC.staleness_of(item))
    except:break

driver.quit()

Мое предложение: Селен

Если вы хотите изменить страницу автоматически, вы можете использовать Selenium WebDriver. Selenium дает вам возможность взаимодействовать со страницей, нажимать на кнопки, писать на входах и т. д. Вам нужно будет изменить свой код, чтобы удалить data затем нажмите на older кнопка. Затем он изменит страницу и продолжит соскоб.

Selenium это очень полезный инструмент. Я использую это прямо сейчас, в личном проекте. Вы можете взглянуть на мой репозиторий на GitHub, чтобы увидеть, как он работает. В случае страницы, которую вы пытаетесь удалить, вы не можете перейти на старую, просто изменив link быть scrapedИтак, вам нужно использовать Selenium делать изменения между страницами.

Надеюсь, поможет.

Нет необходимости использовать Selenium в текущем случае. Перед очисткой необходимо открыть URL-адрес в браузере и нажать клавишу F12, чтобы проверить код и увидеть пакеты на вкладке "Сеть". Когда вы нажимаете "Далее" или "OLDER", в вашем случае вы можете увидеть новый набор TCP-пакетов на вкладке "Сеть". Он предоставит вам все, что вам нужно. Когда вы понимаете, как это работает, вы можете написать работающий паук.

import scrapy
from scrapy import FormRequest
from scrapy.contrib.spiders import CrawlSpider,Rule
from scrapy.contrib.linkextractors import LinkExtractor



class Roto_News_Spider2(CrawlSpider):
    name = "RotoPlayerNews"

    start_urls = [
        'http://www.<DOMAIN>/playernews/nfl/football/',
    ]

    Rules = (Rule(LinkExtractor(allow=(), restrict_xpaths=('//input[@id="cp1_ctl00_btnNavigate1"]',)), callback="parse", follow= True),)


    def parse(self, response):
        for item in response.xpath("//div[@class='pb']"):
            player = item.xpath(".//div[@class='player']/a/text()").extract_first()
            position= item.xpath(".//div[@class='player']/text()").extract()[0].replace("-","").strip()
            team = item.xpath(".//div[@class='player']/a/text()").extract()[1].strip()
            report = item.xpath(".//div[@class='report']/p/text()").extract_first()
            date = item.xpath(".//div[@class='date']/text()").extract_first() + " 2018"
            impact = item.xpath(".//div[@class='impact']/text()").extract_first().strip()
            source = item.xpath(".//div[@class='source']/a/text()").extract_first()
            yield {"Player": player,"Position": position, "Team": team,"Report":report,"Impact":impact,"Date":date,"Source":source}

        older = response.css('input#cp1_ctl00_btnNavigate1')
        if not older:
            return

        inputs = response.css('div.aspNetHidden input')
        inputs.extend(response.css('div.RW_pn input'))

        formdata = {}
        for input in inputs:
            name = input.css('::attr(name)').extract_first()
            value = input.css('::attr(value)').extract_first()
            formdata[name] = value or ''

        formdata['ctl00$cp1$ctl00$btnNavigate1.x'] = '42'
        formdata['ctl00$cp1$ctl00$btnNavigate1.y'] = '17'
        del formdata['ctl00$cp1$ctl00$btnFilterResults']
        del formdata['ctl00$cp1$ctl00$btnNavigate1']

        action_url = 'http://www.<DOMAIN>/playernews/nfl/football-player-news?ls=roto%3anfl%3agnav&rw=1'

        yield FormRequest(
            action_url,
            formdata=formdata,
            callback=self.parse
        )

Будьте осторожны, вам нужно заменить все на одно в моем коде.

Другие вопросы по тегам