Extraction et stockage de données avec Scrapy

  • pySpider

Qu'est-ce qu'un framework ?

  • C'est un modèle de projet hautement réutilisable intégrant plusieurs fonctionnalités (applicable à divers besoins)

Fonctionnalités intégrées par Scrapy :

  • Opérations d'analyse de données performantes (XPath)
  • Téléchargement de données haute performance
  • Stockage persistant hautement efficace
  • Middleware
  • Opérations complètes de scraping
  • Distribution : Redis
  • Mécanisme de passage de paramètres dans les requêtes (crawl en profondeur)
  • Intégration raisonnable de Selenium dans Scrapy

Installation de l'environnement :

  1. pip3 install wheel
  2. Télécharger Twisted depuis http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
  3. Dans le dossier de téléchargement, exécuter pip3 install Twisted‑17.1.0‑cp35‑cp35m‑win_amd64.whl
  4. pip3 install pywin32
  5. pip3 install scrapy

Création d'un projet :

  • scrapy startproject ProName
  • cd ProName
  • scrapy genspider spiderName www.xxx.com : création d'un fichier spider
  • Exécution : scrapy crawl spiderName
  • Paramètres (settings) :
    • Ne pas respecter le fichier robots.txt
    • Usurpation d'UA
    • LOG_LEVEL = 'ERROR'
    • LOG_FILE = 'logging.log'

Extraction des données avec Scrapy :

  • extract() : retourne une liste de résultats
  • extract_first() : retourne uniquement le premier résultat

Stockage persistant avec Scrapy :

  • Via commandes terminales :
    • Seulement les retours de la méthode parse peuvent être sauvegardés sur le disque
    • scrapy crawl first -o file.csv
  • Via pipelines (pipelines.py) :
    • Processus de codage :
      1. Extraction des données
      2. Définition des attributs dans la classe Item
      3. Encapsulation des données extraites dans un objet de type Item : item['p']
      4. Transmission de l'objet Item au pipeline
      5. Méthode process_item du pipeline reçoit l'objet Item pour un stockage persistant selon les besoins
      6. Activation du pipeline dans le fichier de configuration

Remarques :

  • Chaque classe pipeline représente un type spécifique de stockage.
  • Si plusieurs classes sont définies, l'objet Item est transmis à celle ayant la priorité la plus élevée.
  • Retourner item dans process_item permet de transmettre l'objet au pipeline suivant.

Exemple : Récupération des noms, pseudos et popularité des streams sur HuYa

Première méthode de stockage (via terminal)

Code de l'instance hy.py :

# -*- coding: utf-8 -*-
import scrapy

class HySpider(scrapy.Spider):
    name = 'hy'
    # allowed_domains = ['www.xx.com']
    start_urls = ['https://www.huya.com/g/3203']

    def parse(self, response):
        li_list = response.xpath('//*[@id="js-live-list"]/li')
        data = []
        for li in li_list:
            title = li.xpath("./a[2]/text()").extract_first()
            nick = li.xpath("./span/span[1]/i/text()").extract_first()
            hot = li.xpath("./span/span[2]/i[2]/text()").extract_first()
            dic = {"title": title, "nick": nick, "hot": hot}
            data.append(dic)
        return data

Dans le terminal de PyCharm, exécuter la commande : scrapy crawl hy -o huya.csv

Deuxième méthode de stockage (via pipeline)

Code hy.py :

# -*- coding: utf-8 -*-
import scrapy
from huya.items import HuyaItem

class HySpider(scrapy.Spider):
    name = 'hy'
    # allowed_domains = ['www.xx.com']
    start_urls = ['https://www.huya.com/g/3203']

    def parse(self, response):
        li_list = response.xpath('//*[@id="js-live-list"]/li')
        for li in li_list:
            title = li.xpath("./a[2]/text()").extract_first()
            nick = li.xpath("./span/span[1]/i/text()").extract_first()
            hot = li.xpath("./span/span[2]/i[2]/text()").extract_first()
            item = HuyaItem()
            item["title"] = title
            item["nick"] = nick
            item["hot"] = hot
            yield item

Classe Item :

# -*- coding: utf-8 -*-

# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html

import scrapy

class HuyaItem(scrapy.Item):
    title = scrapy.Field()
    nick = scrapy.Field()
    hot = scrapy.Field()

Classe Pipeline (stockage local et MySQL) :

# -*- coding: utf-8 -*-

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
import pymysql

class HuyaPipeline(object):
    def open_spider(self, spider):
        print("open_spider start work...")
        self.fp = open("huya.txt", "w", encoding="utf-8")

    def process_item(self, item, spider):
        self.fp.write(item["title"] + "--" + item["nick"] + "--" + item["hot"] + "\n")
        print(item["title"] + ": stockage terminé...")
        return item

    def close_spider(self, spider):
        print("close_spider end work...")
        self.fp.close()

class mysqlPipeline(object):
    def open_spider(self, spider):
        print("open_spider start work...")
        self.conn = pymysql.Connect(host="127.0.0.1", port=3306, user="root", password="root", db="Spider", charset="utf8")

    def process_item(self, item, spider):
        sql = "insert into huya values ('%s','%s','%s')" % (item["title"], item["nick"], item["hot"])
        self.cursor = self.conn.cursor()
        try:
            self.cursor.execute(sql)
            self.conn.commit()
        except Exception as e:
            self.conn.rollback()
        return item

    def close_spider(self, spider):
        print("close_spider end work...")

Modification nécessaire dans settings.py :

ITEM_PIPELINES = {
    'huya.pipelines.HuyaPipeline': 300,
    'huya.pipelines.mysqlPipeline': 301
}

Pour synchroniser avec Redis, ajouter cette classe dans le pipeline :

class RedisPipeLine(object):
    conn = None

    def open_spider(self, spider):
        self.conn = Redis(host='127.0.0.1', port=6379)

    def process_item(self, item, spider):
        self.conn.lpush('huyaList', item)
        return item

Modifier ITEM_PIPELINES dans settings.py pour inclure cette classe.

Étiquettes: Scrapy Python web scraping Data extraction pipelines

Publié le 16 septembre à 02h42