Очистка "старых" страниц с помощью scrapy, правил и экстракторов ссылок - PullRequest
0 голосов
/ 10 июня 2018

Я работал над проектом со скрапом.С помощью этого прекрасного сообщества мне удалось почистить первую страницу этого сайта: 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 ]

0 голосов
/ 11 июня 2018

Нет необходимости использовать 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
        )

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

0 голосов
/ 11 июня 2018

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

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

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()
0 голосов
/ 10 июня 2018

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

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

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

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

...