web-dev-qa-db-fra.com

Comment exécuter une araignée Scrapy à partir d'AWS Lambda?

J'essaie d'exécuter une araignée grinçante à partir d'AWS Lambda. Voici à quoi ressemble mon script actuel, qui consiste à gratter les données de test.

import boto3
import scrapy
from scrapy.crawler import CrawlerProcess

s3 = boto3.client('s3')
BUCKET = 'sample-bucket'

class BookSpider(scrapy.Spider):
    name = 'bookspider'
    start_urls = [
        'http://books.toscrape.com/'
    ]

    def parse(self, response):
        for link in response.xpath('//article[@class="product_pod"]/div/a/@href').extract():
            yield response.follow(link, callback=self.parse_detail)
        next_page = response.xpath('//li[@class="next"]/a/@href').extract_first()
        if next_page:
            yield response.follow(next_page, callback=self.parse)

    def parse_detail(self, response):
        title = response.xpath('//div[contains(@class, "product_main")]/h1/text()').extract_first()
        price = response.xpath('//div[contains(@class, "product_main")]/'
                               'p[@class="price_color"]/text()').extract_first()
        availability = response.xpath('//div[contains(@class, "product_main")]/'
                                      'p[contains(@class, "availability")]/text()').extract()
        availability = ''.join(availability).strip()
        upc = response.xpath('//th[contains(text(), "UPC")]/'
                             'following-sibling::td/text()').extract_first()
        yield {
            'title': title,
            'price': price,
            'availability': availability,
            'upc': upc
        }

def main(event, context):
    process = CrawlerProcess({
        'USER_AGENT': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)',
        'FEED_FORMAT': 'json',
        'FEED_URI': 'result.json'
    })

    process.crawl(BookSpider)
    process.start() # the script will block here until the crawling is finished

    data = open('result.json', 'rb')
    s3.put_object(Bucket = BUCKET, Key='result.json', Body=data)
    print('All done.')

if __name__ == "__main__":
    main('', '')

J'ai d'abord testé ce script localement et il fonctionnait normalement, en grattant les données et en les enregistrant dans un "results.json", puis en le téléchargeant sur mon compartiment S3.

Ensuite, j'ai configuré ma fonction AWS Lambda en suivant le guide ici: https://serverless.com/blog/serverless-python-packaging/ et il importe avec succès la bibliothèque Scrapy dans AWS Lambda pour exécution.

Cependant, lorsque le script est exécuté sur AWS Lambda, il n'efface pas les données et renvoie simplement une erreur pour results.json n'existe pas

Quiconque a configuré l'exécution de Scrapy ou a une solution de contournement ou peut me diriger dans la bonne direction serait très apprécié.

Merci.

8
U. Tayyab

Je suis juste tombé sur cela en cherchant autre chose, mais du haut de ma tête ..

Les Lambdas fournissent un stockage temporaire dans/tmp, donc je suggère de définir

'FEED_URI': '/tmp/result.json'

Puis

data = open('/tmp/result.json', 'rb')

Il y a probablement toutes sortes de meilleures pratiques autour de l'utilisation du stockage temporaire dans les lambdas, donc je suggère de passer un peu de temps à les lire.

6
Joe