IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

NodeJS Discussion :

Générer un fichier JSON avec Puppeteer


Sujet :

NodeJS

  1. #1
    Membre à l'essai
    Homme Profil pro
    Apprenti ingénieur informatique
    Inscrit en
    Mai 2017
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Apprenti ingénieur informatique

    Informations forums :
    Inscription : Mai 2017
    Messages : 13
    Points : 16
    Points
    16
    Par défaut Générer un fichier JSON avec Puppeteer
    Bonjour à toutes et à tous,

    Je viens de commencer mon alternance dans une TPE de développement web, et je suis le seul à faire du NodeJS. Je vous explique mon problème, j'ai développé une petite API avec Puppeteer permettant de faire du web scraping sur des sites dynamiques. Mon API me renvoie dans la console ce que j'ai récupéré au format JSON, et je souhaiterais enregistrer ce contenu dans un fichier JSON. J'ai utilisé le paquet 'fs', puis j'ai utilisé la méthode wrietFileSync de ce paquet pour écrire le contenu du site au format JSON dans mon fichier, mais quand je lance mon script, ça me renvoie :
    Nom : Capture.PNG
Affichages : 855
Taille : 19,0 Ko

    Bien-sûr j'ai cherché de mon côté pour voir si je trouvais quelque chose, mais malheureusement mes recherches ont été infructueuses...
    Je joins le code de l'API :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    const puppeteer = require('puppeteer')
    const fs = require('fs')
     
    let bookingUrl = 'https://www.astrazeneca.com/media-centre/press-releases.html';
    (async () => {
        const browser = await puppeteer.launch({ headless: true })
        const page = await browser.newPage()
        await page.setViewport({ width: 1920, height: 926 })
        await page.goto(bookingUrl)
     
        // Get page details
        let newsData = await page.evaluate(() => {
            let news = []
            let newsElements = document.querySelectorAll('.filter-items__results-list .filter-items__results-list-item')
            newsElements.forEach((newsElement) => {
                let newsJson = {}
                try {
                    newsJson.name = newsElement.querySelector('a div .filter-items__results-item-title').innerText
                    newsJson.elmementLink = newsElement.querySelector('.filter-items__results-item').href
                    newsJson.created = Date.now()
                    newsJson.abstract = ''
                }
                catch (exception) {
     
                }
                news.push(newsJson)
            })
            const newsTrimmed = news.filter(n => n !== undefined)
            fs.writeFileSync('news.json',
                JSON.stringify(newsTrimmed, null, 4),
                (err) => console.log('File successfully written !'))
            return news
        })
        console.dir(newsData)
    })()
    Merci d'avance !

  2. #2
    Membre émérite Avatar de tsuji
    Inscrit en
    Octobre 2011
    Messages
    1 558
    Détails du profil
    Informations forums :
    Inscription : Octobre 2011
    Messages : 1 558
    Points : 2 736
    Points
    2 736
    Par défaut
    C'est une erreur dotée une immense ambiguïté malheureusement, en particulièrement une mention de ReferenceError fs comme si fs n'est pas reconnu dans la portée. Pour résoudre l'erreur Evaluation failed ... on peut mettre un try-catch autour de fs.writeFileSync().
    Code node.js : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
            try {
                fs.writeFileSync('news.json',
                    JSON.stringify(newsTrimmed, null, 4),
                    (err) => console.log('File successfully written !'))
            } catch (exception) {
                //comme on veut
            }
            return news
    Dans le futur, comment ça se comporte, je ne sais pas.

  3. #3
    Invité
    Invité(e)
    Par défaut
    slt,

    ce qui met la puce à l'oreille c'est le executionContext dans ta stacktrace

    en fait le js que tu ecris est interprété non pas par v8 (de nodejs) mais par celui du moteur de puppeteer.
    et lui il connait pas fs (et quand bien même, il faudrait que tu ecrives require('fs') au sein de page.evaluate

    il y a peut etre moyen de passer des arguments à puppeteer mais sinon tu peux simplement utiliser fs apres:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
        // Get page details
        let newsData = await page.evaluate(() => {
            ...
        })
        //we are now back in nodeJS scope
        fs.writeFileSync('news.json',
            JSON.stringify(newsData, null, 4),
            (err) => console.log('File successfully written !'))

  4. #4
    Membre émérite Avatar de tsuji
    Inscrit en
    Octobre 2011
    Messages
    1 558
    Détails du profil
    Informations forums :
    Inscription : Octobre 2011
    Messages : 1 558
    Points : 2 736
    Points
    2 736
    Par défaut
    Je tiens juste à souligner, je pense c'est important, que la référence ou la variable fs est bien reconnue à l'endroit-là, donc, les règles qui dictent la portée de la déclaration d'une variable n'est pas mise en question. La preuve est que le code que j'apporte avec une construction try-catch mène une bonne fin en effet. Le problème proviendrait probablement de l'implémentation de la promesse es6+ - mais je n'en suis pas 100% certain !

  5. #5
    Invité
    Invité(e)
    Par défaut
    ton code ne mènerait il pas une bonne fin parce que justement tu catches l'exception?
    le but n'est pas de masquer lexception mais d'écrire dans le fichier. Confirmes tu que le fichier est bien écrit? (parce que quand je vois une stacktrace avec fs not defined... )

  6. #6
    Membre à l'essai
    Homme Profil pro
    Apprenti ingénieur informatique
    Inscrit en
    Mai 2017
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Apprenti ingénieur informatique

    Informations forums :
    Inscription : Mai 2017
    Messages : 13
    Points : 16
    Points
    16
    Par défaut
    Après quelques recherches, j'ai trouvé la solution :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
    const puppeteer = require('puppeteer')
    const fs = require('fs-extra');
     
    (async () => {
        try {
            const browser = await puppeteer.launch({ headless: true })
            const page = await browser.newPage()
            page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36')
            await page.goto('https://www.nasa.gov/news/releases/latest/index.html')
            await page.waitForSelector('.ubernode-listing')
            let news = []
            let json = {}
            const sections = await page.$$('.ubernode')
            for (let section of sections) {
                json.id = await Math.random()
                json.title = await section.$eval('h3 a', el => el.innerText)
                json.url = await section.$eval('h3 a', el => el.href)
                json.date = Date.parse(await section.$eval('p', el => el.innerText))
                json.abstract = await section.$eval('p', el => el.innerText)
                await news.push(json)
            }
            let newsTrimmed = await news.filter(n => n !== undefined)
            await fs.writeFile('news.json',
                JSON.stringify(newsTrimmed, null, 4),
                (err) => console.log('File successfully writen !')
            )
            await browser.close()
            return news
        } catch (exception) {
            console.log('Our error : ' + exception)
        }
    })()

  7. #7
    Invité
    Invité(e)
    Par défaut
    hello

    Je pense que t'as pas compris à quoi sert await. ca veut dire:

    ATTEND que mon truc de droite qui est ASYNCHRONE me retourne un résultat.

    Si le truc de droite est synchrone, alors t'as le résultat direct, ca ne sert __à rien__ d'écrire await.
    donc les

    1)

    a = await 1
    a = await []
    a = await [].filter(_=>{})
    a = await [].push(json)
    a = await Math.random()

    ou je sais pas squoi d'autre, c'est useless!!

    2)
    soit dit en passant fs-extra: serieusement?? pour ecrire juste dans 1 fichier, tu rajoutes une dependance?

    surtout qu'en plus tu utilises writeFileSync


    ===bonus point

    ton news.filter(n=>n!==undefined) est inutile.

    TOUS les elements de news ont été pushé à partir de la variable json qui vaut intialement {}

    Or, {} !==undefined, cqui veut dire que ton filter ... ne filtre rien.

    ===bonus point 2

    la variable let json réfère à un objet, et en itérant (boucle for) tu modifies json... qui réfère tjs au même objet...

    idem
    json = {}
    news = []
    json.id = 0
    news.push(json) //[{id:0}]
    json.id = 1
    news.push(json) //[{id:1},{id:1}] <=meme reference vers le même objet...
    donc mieux d'enquiller ton let json __dans__ la boucle for

  8. #8
    Membre émérite Avatar de tsuji
    Inscrit en
    Octobre 2011
    Messages
    1 558
    Détails du profil
    Informations forums :
    Inscription : Octobre 2011
    Messages : 1 558
    Points : 2 736
    Points
    2 736
    Par défaut
    @galerien69
    Merci pour tes remarques (26/09/2018 #5). Tu as raison et je m'étais trompé l'essentiel. Même on redéclare require('fs') dedans page.evaluate(), elle n'est pas reconnue non plus. Encore, mes appréciations.

  9. #9
    Membre à l'essai
    Homme Profil pro
    Apprenti ingénieur informatique
    Inscrit en
    Mai 2017
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Apprenti ingénieur informatique

    Informations forums :
    Inscription : Mai 2017
    Messages : 13
    Points : 16
    Points
    16
    Par défaut
    Oui en effet, au temps pour moi. Merci

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [AJAX] Récupération d'un fichier JSON avec javaScript
    Par guerin dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 26/11/2006, 20h05
  2. [Excel] Générer des fichiers Excel avec PHP et des données SQL
    Par MaTHieU_ dans le forum Bibliothèques et frameworks
    Réponses: 3
    Dernier message: 29/03/2006, 16h46
  3. Générer un fichier résultat avec sépateur ;
    Par soulryo dans le forum MS SQL Server
    Réponses: 8
    Dernier message: 30/08/2005, 10h57
  4. Générer un fichier résultat avec sépateur ;
    Par soulryo dans le forum Langage SQL
    Réponses: 3
    Dernier message: 29/08/2005, 13h29
  5. générer un fichier svg avec le bon encoding
    Par TOM-Z dans le forum XML/XSL et SOAP
    Réponses: 3
    Dernier message: 24/08/2005, 18h39

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo