Scrapy для загрузки файлов определенного типа - PullRequest
0 голосов
/ 16 ноября 2018

Я новичок в scrapy и python, я могу загружать все файлы, но я хочу загружать только файлы определенного типа "EX-10", чтобы он мог загружать следующие файлы. (Ex-10.1, Ex-10.2 - EX-10.99).

Мой код

import scrapy, os

class legco(scrapy.Spider):
name = "sec_gov"

start_urls = ["https://www.sec.gov/cgi-bin/browse-edgar?action=getcompany&SIC=2834&owner=exclude&match=&start=120&count=40&hidefilings=0"]

def parse(self, response):
    for link in response.xpath('//table[@summary="Results"]//td[@scope="row"]/a/@href').extract():
        absoluteLink = response.urljoin(link)
        yield scrapy.Request(url = absoluteLink, callback = self.parse_links)

def parse_links(self, response):
    for links in response.xpath('//table[@summary="Results"]//a[@id="documentsbutton"]/@href').extract():
        targetLink = response.urljoin(links)
        yield scrapy.Request(url = targetLink, callback = self.collecting_file_links)

def collecting_file_links(self, response):
    for links in response.xpath('//table[contains(@summary,"Document")]//td[@scope="row"]/a/@href').extract():
        if links.endswith(".htm") or links.endswith(".txt"):
            baseLink = response.urljoin(links)
            yield scrapy.Request(url = baseLink, callback = self.download_files)

def download_files(self, response):
    path = response.url.split('/')[-1]
    dirf = r"/home/surukam/scrapy/demo/tutorial/tutorial/Downloads3"
    if not os.path.exists(dirf):os.makedirs(dirf)
    os.chdir(dirf)
    with open(path, 'wb') as f:
        f.write(response.body)

и Scrapy хотят также проверить следующие страницы ... (до последней страницы), не работает Отлично.

Rules = (Rule(LinkExtractor(allow=(), restrict_xpaths=('//a[@value="Next 40"]',)), callback="parse", follow= True),)

# follow next page links
    next_page = response.xpath('.//a[@value="Next 40"]/@href').extract()
    if next_page:
        next_href = next_page[0]
        next_page_url = 'https://www.sec.gov/cgi-bin/browse-edgar?company=&match=&CIK=&filenum=&State=&Country=&SIC=2834&owner=exclude&Find=Find+Companies&action=getcompany' + next_href
        request = scrapy.Request(url=next_page_url)
        yield request

Ответы [ 2 ]

0 голосов
/ 17 ноября 2018

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

import scrapy, os

class legco(scrapy.Spider):
    name = "sec_gov"

    start_urls = ["https://www.sec.gov/cgi-bin/browse-edgar?action=getcompany&SIC=2834&owner=exclude&match=&start=120&count=40&hidefilings=0"]

    def parse(self, response):
        for link in response.xpath('//table[@summary="Results"]//td[@scope="row"]/a/@href').extract():
            absoluteLink = response.urljoin(link)
            yield scrapy.Request(url = absoluteLink, callback = self.parse_links)

        nextpage = response.css("input[value='Next 40']::attr(onclick)")
        if nextpage:
            tpage = nextpage.extract_first().split("parent.location=")[1].replace("'","")
            nlink = response.urljoin(tpage)
            yield scrapy.Request(url=nlink, callback = self.parse)

    def parse_links(self, response):
        for links in response.xpath('//table[@summary="Results"]//a[@id="documentsbutton"]/@href').extract():
            targetLink = response.urljoin(links)
            yield scrapy.Request(url = targetLink, callback = self.collecting_file_links)

    def collecting_file_links(self, response):
        for links in response.xpath('//table[contains(@summary,"Document")]//tr[td[starts-with(., "EX-")]]/td/a[contains(@href, ".htm") or contains(@href, ".txt")]/@href').extract():
            baseLink = response.urljoin(links)
            yield scrapy.Request(url = baseLink, callback = self.download_files)

    def download_files(self, response):
        path = response.url.split('/')[-1]
        dirf = r"/home/surukam/scrapy/demo/tutorial/tutorial/Downloads3"
        if not os.path.exists(dirf):os.makedirs(dirf)
        os.chdir(dirf)
        with open(path, 'wb') as f:
            f.write(response.body)
0 голосов
/ 16 ноября 2018

Вам нужно использовать FilesPipeline, но тот, который предоставляет scrapy, генерирует имя файла на основе хеша URL.

Если вам нужно произвольное имя файла, вы должны сделать свое собственное FilesPipeline, например:

import scrapy, os
from scrapy.pipelines.files import FilesPipeline

class legco(scrapy.Spider):
    name = "sec_gov"

    start_urls = ["https://www.sec.gov/cgi-bin/browse-edgar?action=getcompany&SIC=2834&owner=exclude&match=&start=120&count=40&hidefilings=0"]

    custom_settings = {
        'ITEM_PIPELINES': {'myspider.MyFilesPipeline': 1},
        'FILES_STORE': '/my/valid/path/',
    }

    def parse(self, response):
        for link in response.xpath('//table[@summary="Results"]//td[@scope="row"]/a/@href').extract():
            absoluteLink = response.urljoin(link)
            yield scrapy.Request(url = absoluteLink, callback = self.parse_links)

    def parse_links(self, response):
        for links in response.xpath('//table[@summary="Results"]//a[@id="documentsbutton"]/@href').extract():
            targetLink = response.urljoin(links)
            yield scrapy.Request(url = targetLink, callback = self.collecting_file_links)

    def collecting_file_links(self, response):
        for links in response.xpath('//table[contains(@summary,"Document")]//td[@scope="row"]/a/@href').extract():
            if links.endswith(".htm") or links.endswith(".txt"):
                yield {
                    'file_urls': [response.urljoin(links)]
                }

class MyFilesPipeline(FilesPipeline):

    def file_path(self, request, response=None, info=None):
        return request.url.split('/')[-1]
...