[PYTHON] Grattage sans serveur régulier avec AWS lambda + scrapy, partie 1

Premier poste! Je voulais vraiment inclure le serveur sans serveur dans un article, mais je ne pouvais pas le faire à temps ... Donc, cette fois, ce sera l'édition de grattage.

Chose que tu veux faire

Je souhaite gratter automatiquement les pages Web dont les informations sont mises à jour régulièrement!

Cible

Obtenez des données Yahoo! Weather (Tokyo) toutes les 6 heures.

Méthode

Python + Scrapy + AWSlambda + CroudWatchEvents semble être bon ...?

Je vais l'essayer pour le moment

D'abord de grattage

Suivez les étapes ci-dessous pour créer les pièces d'exploration et de grattage.

  1. Installation scrapy
  2. Créer un projet Scrapy
  3. Créer une araignée
  4. Exécuter

1. Installation scrapy

$ python3 -V
Python 3.7.4

$ pip3 install scrapy
...
Successfully installed

$ scrapy version
Scrapy 1.8.0

2. Créez un projet Scrapy

Un dossier pour votre projet sera créé dans la hiérarchie où vous avez entré la commande.

$ scrapy startproject yahoo_weather_crawl
New Scrapy project 'yahoo_weather_crawl'

$ ls
yahoo_weather_crawl

Cette fois, je vais essayer d'obtenir cette partie de la météo yahoo. image.png Prenons la date de l'annonce, la date, la météo, la température et la probabilité de précipitations.

Scrapy a un shell de ligne de commande, et vous pouvez entrer des commandes pour vérifier si la cible d'acquisition est correctement prise, alors procédons en la vérifiant une fois.

Spécifiez la cible d'acquisition avec xpath. Vous pouvez facilement obtenir le xpath à partir des outils de développement Google Chrome (celui qui sort lorsque vous appuyez sur F12).

image.png

Le xpath de la date et de l'heure d'annonce acquise cette fois est le suivant //*[@id="week"]/p

Tirons cela de la réponse.


#Commencer la coquille tremblante
$ scrapy shell https://weather.yahoo.co.jp/weather/jp/13/4410.html

>>> announcement_date = response.xpath('//*[@id="week"]/p/text()').extract_first()
>>> announcement_date
'Annoncé à 18h00 le 29 novembre 2019'

Si vous spécifiez text (), vous ne pouvez obtenir que le texte. Pour plus d'informations, consultez Références.

Pour le moment, la date et l'heure ont été fixées, alors passons les autres de la même manière.

Les autres informations se trouvent dans la balise table, donc récupérez une fois tout le contenu de la table.

image.png


>>> table = response.xpath('//*[@id="yjw_week"]/table')

Vous avez maintenant les éléments dans la balise table pour ```id = "yjw_week" `` `. Obtenez chaque élément d'ici.


#Date
>>> date = table.xpath('//tr[1]/td[2]/small/text()').extract_first()
>>> date
'1er décembre'

#Météo
>>> weather = table.xpath('//tr[2]/td[2]/small/text()').extract_first()
>>> weather
'Nuageux et parfois ensoleillé'

#Température
>>> temperature = table.xpath('//tr[3]/td[2]/small/font/text()').extract()
>>> temperature
['14', '5']

#pour cent pluvieux
>>> rainy_percent = table.xpath('//tr[4]/td[2]/small/text()').extract_first()
>>> rainy_percent
'20'

Maintenant que vous savez comment obtenir chacun Nous allons créer une araignée (la partie principale du processus).

3. Créer une araignée

La structure du dossier de projet créé précédemment est la suivante.


.
├── scrapy.cfg
└── yahoo_weather_crawl
    ├── __init__.py
    ├── __pycache__
    ├── items.py
    ├── middlewares.py
    ├── pipelines.py
    ├── settings.py
    └── spiders
        ├── __init__.py
        └── __pycache__

Tout d'abord, définissez les objets à acquérir.

items.py



import scrapy

class YahooWeatherCrawlItem(scrapy.Item):
    announcement_date = scrapy.Field()  #Date et heure de l'annonce
    date = scrapy.Field()               #Date
    weather = scrapy.Field()            #Météo
    temperature = scrapy.Field()        #Température
    rainy_percent = scrapy.Field()      #pour cent pluvieux

Ensuite, créez le corps de l'araignée dans le dossier des araignées.

spider/weather_spider.py


# -*- coding: utf-8 -*-
import scrapy
from yahoo_weather_crawl.items import YahooWeatherCrawlItem

# spider
class YahooWeatherSpider(scrapy.Spider):

    name = "yahoo_weather_crawler"
    allowed_domains = ['weather.yahoo.co.jp']
    start_urls = ["https://weather.yahoo.co.jp/weather/jp/13/4410.html"]

    #Processus d'extraction pour réponse
    def parse(self, response):
        #Date et heure de l'annonce
        yield YahooWeatherCrawlItem(announcement_date = response.xpath('//*[@id="week"]/p/text()').extract_first())
        table = response.xpath('//*[@id="yjw_week"]/table')

        #Boucle de date
        for day in range(2, 7):

            yield YahooWeatherCrawlItem(
                #Extraction de données
                date=table.xpath('//tr[1]/td[%d]/small/text()' % day).extract_first(),
                weather=table.xpath('//tr[2]/td[%d]/small/text()' % day).extract_first(),
                temperature=table.xpath('//tr[3]/td[%d]/small/font/text()' % day).extract(),
                rainy_percent=table.xpath('//tr[4]/td[%d]/small/text()' % day).extract_first(),
                )

4. Maintenant, cours!

scrapy crawl yahoo_weather_crawler

2019-12-01 20:17:21 [scrapy.core.scraper] DEBUG: Scraped from <200 https://weather.yahoo.co.jp/weather/jp/13/4410.html>
{'announcement_date': 'Annoncé à 17h00 le 1er décembre 2019'}
2019-12-01 20:17:21 [scrapy.core.scraper] DEBUG: Scraped from <200 https://weather.yahoo.co.jp/weather/jp/13/4410.html>
{'date': '3 décembre',
 'rainy_percent': '10',
 'temperature': ['17', '10'],
 'weather': 'Ensoleillé'}
2019-12-01 20:17:21 [scrapy.core.scraper] DEBUG: Scraped from <200 https://weather.yahoo.co.jp/weather/jp/13/4410.html>
{'date': '4 décembre',
 'rainy_percent': '0',
 'temperature': ['15', '4'],
 'weather': 'Ensoleillé'}
2019-12-01 20:17:21 [scrapy.core.scraper] DEBUG: Scraped from <200 https://weather.yahoo.co.jp/weather/jp/13/4410.html>
{'date': '5 décembre',
 'rainy_percent': '0',
 'temperature': ['14', '4'],
 'weather': 'Partiellement nuageux'}
2019-12-01 20:17:21 [scrapy.core.scraper] DEBUG: Scraped from <200 https://weather.yahoo.co.jp/weather/jp/13/4410.html>
{'date': '6 décembre',
 'rainy_percent': '10',
 'temperature': ['11', '4'],
 'weather': 'Nuageux'}
2019-12-01 20:17:21 [scrapy.core.scraper] DEBUG: Scraped from <200 https://weather.yahoo.co.jp/weather/jp/13/4410.html>
{'date': '7 décembre',
 'rainy_percent': '30',
 'temperature': ['9', '3'],
 'weather': 'Nuageux'}

On dirait que c'est bien pris! C'est un gros problème, alors exportons-le dans un fichier.

Lors de la sortie dans un fichier, les caractères japonais seront déformés par défaut, donc Ajoutez les paramètres d'encodage à settings.py.

settings.py


FEED_EXPORT_ENCODING='utf-8'
$ scrapy crawl yahoo_weather_crawler -o weather_data.json
...

weather_data.json


[
{"announcement_date": "Annoncé à 17h00 le 1er décembre 2019"},
{"date": "3 décembre", "weather": "Ensoleillé", "temperature": ["17", "10"], "rainy_percent": "10"},
{"date": "4 décembre", "weather": "Ensoleillé", "temperature": ["15", "4"], "rainy_percent": "0"},
{"date": "5 décembre", "weather": "Partiellement nuageux", "temperature": ["14", "4"], "rainy_percent": "0"},
{"date": "6 décembre", "weather": "Nuageux", "temperature": ["11", "4"], "rainy_percent": "10"},
{"date": "7 décembre", "weather": "Nuageux", "temperature": ["9", "3"], "rainy_percent": "30"}
]

J'ai pu sortir!

La prochaine fois, je combinerai ce processus avec AWS pour l'exécuter sans serveur.

Les références

Scrapy 1.8 documentation https://doc.scrapy.org/en/latest/index.html Scrapy à comprendre en 10 minutes https://qiita.com/Chanmoro/items/f4df85eb73b18d902739 Grattage Web avec Scrapy https://qiita.com/Amtkxa/items/4c1172c932264ae941b4

Recommended Posts

Grattage sans serveur régulier avec AWS lambda + scrapy, partie 1
Déplacer régulièrement les journaux CloudWatch vers S3 avec Lambda
Déployer la fonction Python 3 avec Serverless Framework sur AWS Lambda
Créer une application Web de type Flask / Bottle sur AWS Lambda avec Chalice
Comment créer une API de machine learning sans serveur avec AWS Lambda
J'ai créé un robot pour publier sur Twitter en grattant sur le Web un site dynamique avec AWS Lambda (suite)
Utilisez AWS lambda pour récupérer les actualités et notifier régulièrement LINE des mises à jour [python]
Exécutez régulièrement des programmes Python sur AWS Lambda
Créez un environnement WardPress sur AWS avec Pulumi
Essayez Tensorflow avec une instance GPU sur AWS
Application sans serveur avec AWS SAM! (APIGATEWAY + Lambda (Python))
Scraping avec Python, publication sur TwitterBot, exécution régulière sur Heroku
[AWS] Play with Step Functions (SAM + Lambda) Part.3 (Branch)
Grattage avec coquille tremblante
Créer une couche pour AWS Lambda Python dans Docker
[AWS] Play with Step Functions (SAM + Lambda) Part.1 (Basic)
Je veux AWS Lambda avec Python sur Mac!
Procédure de création d'un Line Bot sur AWS Lambda
[AWS] Play with Step Functions (SAM + Lambda) Part.2 (Paramètres)
Je viens de créer un environnement virtuel avec la couche AWS lambda
Grattage avec Selenium + Python Partie 1
Grattage festif avec Python, scrapy
Déployer Django sans serveur avec Lambda
PyTorch avec AWS Lambda [importation Lambda]
Web scraping à l'aide d'AWS lambda
Grattage avec Selenium + Python Partie 2
[AWS Hands-on] Créons un service d'identification des célébrités avec une architecture sans serveur!
# 3 Créez un environnement Python (Django) avec une instance EC2 (ubuntu18.04) d'AWS part2
Créez une application de scraping avec Python + Django + AWS et modifiez les tâches
Utilisez ScraperWiki pour obtenir régulièrement des données de votre site Web
Lancement d'une application Web sur AWS avec django et modification des tâches
Faisons une discussion WEB en utilisant WebSocket avec AWS sans serveur (Python)!
Jouez avec une tortue avec des graphiques de tortue (partie 1)
Exécutez Python selon la planification sur AWS Lambda
Notifier HipChat avec AWS Lambda (Python)
Procédure de création d'un environnement Kube sur Amazon Linux2 (AWS) ~ (avec bonus)
Préparer l'environnement de Chainer sur l'instance spot EC2 avec AWS Lambda
J'ai essayé de créer un service de raccourcissement d'url sans serveur avec AWS CDK
J'ai écrit un bot Slack qui notifie les informations de retard avec AWS Lambda