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

Symfony PHP Discussion :

Symfony 4, garder le ChromeClient "vivant" (symfony/Panther)


Sujet :

Symfony PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Octobre 2012
    Messages
    172
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Octobre 2012
    Messages : 172
    Par défaut Symfony 4, garder le ChromeClient "vivant" (symfony/Panther)
    Bonjour,

    Contexte ::
    Je développe actuellement un webScrapper utilisant Symfony/Panther et pilotée via une interface WEB (en symfony4) par un utilisateur car le scrap intervient en plusieurs étapes.
    Chaque méthode est lancée au clic utilisateur.

    Code illustratif ::
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $client =\Symfony\Component\Panther\Client::createChromeClient();
            $crawler = $client->request('GET', 'http://www.wikipedia.org/');
            $form = $crawler->filter('#search-form')->form(['search' => 'web scraping']);
            $crawler = $client->submit($form);
            $client->takeScreenshot('pantherScreen.png');
            echo "> Wikipedia :: ".$crawler2->filter('.mw-parser-output p')->first()->text();
    Si on prend ce simple exemple comme illustration, voici ce que j'essai de faire :
    > initialiser le $client une bonne fois pour toute en passant l'étape de connexion (formulaire à remplir puis submit via symfony/panther)
    > réutiliser le $client pour chaque action future
    > 1 clic lancerait par exemple la recherche wikipedia
    > 1 autre clic lancerait la prise d'un screenshot
    etc...

    Mon problème ::
    > 1er clic :: j'initialise le $client, recupére le form, le remplit le submit et tout se passe correctement
    > 2eme clic :: crash car le $client n' "existe" plus

    Pour info, j'ai d'abord développé le script de scrap de A à Z, comprenant connexion, recherche, scrap des résultats, scrap d'un résultat en particulier.
    Le code fonctionne donc c'est bien au moment de séparer les tâches que le soucis arrive parce que je ne garde pas le $client d'un appel à l'autre.

    Mes tentatives ::
    > j'ai regardé la doc du composant "process" de Symfony qui ne me semble pas suffisant à priori !?
    > également regardé du coté du "WorkerThread" de la lib pThread mais qui ne semble pas compatible avec Symfony ???

    Le soucis vient donc du fait que quand je recherche un moyen de faire cela sur le net, je tombe sur plein de libs, composants plus ou moins obscurs... des bouts de lib compatibles sous certaines conditions seulement, dont l'installation est trés fastidieuse etc ou alors il me manque quelque chose...
    Dans le cas du process symfony qui me parraissait le plus prometteur ::
    1/ il me semble que je ne peut communiquer avec mon app symfony qu'une fois celui ci terminé (auquel cas il y a perte du $client)
    2/ une fois le click utilisateur réalisé et le process executé, il semble que je perde toute reference à celui-ci et meme si on peut récupérer le PID dudit process, il semble qu'on ne puisse pas retrouver ce thread grâce à son PID... ca m'a d'ailleurs trés étonné...

    Voila, anciennement dev Android, ce que je cherche à faire aurait été fait en 5mn via une AsyncTask ou un WorkerThread tous deux directement fournis par le framework Android...
    Mais en Web, je piétine et tourne en rond :/

    Ma question ::
    > Comment garder mon instance de $client après la connexion et pour tous les autres appels aux méthodes de scrap au sein d'une app symfony 4...

    D'avance merci pour votre aide

  2. #2
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Octobre 2012
    Messages
    172
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Octobre 2012
    Messages : 172
    Par défaut
    Pour que ce soit plus clair, j'ai fait un micro projet de test pour pouvoir donner "tout" le code ::

    Le controller symfony4 ::
    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    <?php
     
    namespace App\Controller;
     
    use Facebook\WebDriver\Chrome\ChromeOptions;
    use Facebook\WebDriver\Remote\DesiredCapabilities;
    use React\Dns\Config\Config;
    use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Component\HttpFoundation\Session\Session;
    use Symfony\Component\Panther\Client;
    use Symfony\Component\Routing\Annotation\Route;
    use Symfony\Component\DomCrawler\Crawler;
    use Symfony\Component\Panther\PantherTestCase;
     
    class TestController extends AbstractController
    {
        private $client;
     
        /**
         * @Route("/crawler/testclient", name="testclient")
         */
        public function index(/*Request $request*/ Session $session)
        {
            // TODO The client i want to keep alive ::
            $this->client =\Symfony\Component\Panther\Client::createChromeClient();
            $session->set('client', $this->client);
     
            return $this->render('client.html.twig', [
                'example_path' => $this->generateUrl('example')
            ]);
        }
     
        /**
         * @Route("/crawler/example", name="example")
         */
        public function doScrapExampleUsingPanther(Session $session)
        {
            // TODO if we re-create the client it obviously works...
            // TODO but if you have a connexion form to pass, it is lost...
            // $this->client =\Symfony\Component\Panther\Client::createChromeClient();
     
            $crawler = $this->client->request('GET', 'http://example.com');
            $firstParag = $crawler->filter('p')->first()->text();
     
            // TODO tried to use session but doesn't work
            // $c = $session->get('client', $this->client);
            // dump($c);
            // $crawler = $c->request('GET', 'http://example.com');
            // $firstParag = $crawler->filter('p')->first()->text();
     
            return $this->json([
                'result' => '1st par > '.$firstParag
            ]);
        }
    }
    le fichier twig + javascript des clicks button ::
    Code Twig : 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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>{% block title %}ReactPHP Crawler{% endblock %}</title>
        {% block stylesheets %}
            <link href="{{ asset('css/bootstrap.css') }}" type="text/css" rel="stylesheet"/>
            <link href="{{ asset('css/crawler.css') }}" type="text/css" rel="stylesheet"/>
        {% endblock %}
        <script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
    </head>
    <body>
    <span id="helloSpan"> Hello world </span>
    <br/>
    <button id="btn_step1">Step 1 : scrap example.com</button>
    <br/>
     
    {% block body %} {% endblock %}
     
    {% block javascripts %}
        <script>
            $(document).ready(function(){
                console.log("Script working properly");
                // AJAX ::
                $('#btn_step1').on('click', function(){
                    $('#helloSpan').html("btn step 1 clicked");
                    console.log("btn 1 clicked");
                    $.ajax({
                        type:'GET',
                        url :'{{ example_path }}',
                        data:{ },
                        dataType:'json',
                        success: function(data){
                            console.log('> Ajax success step 1');
                            console.log(data["result"]);
                        },
                        error: function(data){
                            alert("> Ajax error step 1");
                            console.log(data);
                        }
                    });
                });
     
            }); // document ready
        </script>
    {% endblock %}
    </body>
    </html>

  3. #3
    Membre extrêmement actif
    Avatar de dukoid
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2012
    Messages
    2 100
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2012
    Messages : 2 100
    Par défaut
    je n'ai pas essayé ton code mais théoriquement on utilise les sessions.

    une session ce conserve un certain temps que l'on peut définir....

  4. #4
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Octobre 2012
    Messages
    172
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Octobre 2012
    Messages : 172
    Par défaut
    j'ai testé la session (cf le code commenté)
    mais ça ne fonctionne pas...

    en fait si j'utilise
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $c = $session->get('client')
    puis
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    // TODO tried to use session but doesn't work
            // $c = $session->get('client);
            // dump($c);
            // $crawler = $c->request('GET', 'http://example.com');
            // $firstParag = $crawler->filter('p')->first()->text();
    Je ne récupère pas le client et tombe dans une error 500...

    Ou alors tu penses que la session pourrait expirer entre l'appel au controller puis le click du bouton ? (1 sec maxi dans mes tests)

  5. #5
    Membre extrêmement actif
    Avatar de dukoid
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2012
    Messages
    2 100
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2012
    Messages : 2 100
    Par défaut
    attention aux version de symfony


    avec symfony 4
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    use Symfony\Component\HttpFoundation\Session\SessionInterface;
     
    public function index(SessionInterface $session)
    {
        // stores an attribute for reuse during a later user request
        $session->set('foo', 'bar');
     
        // gets the attribute set by another controller in another request
        $foobar = $session->get('foobar');
     
        // uses a default value if the attribute doesn't exist
        $filters = $session->get('filters', []);
    }

  6. #6
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Octobre 2012
    Messages
    172
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Octobre 2012
    Messages : 172
    Par défaut
    J'ai fait le changement pour utiliser le SessionInterface.

    Il semble qu'il y ait un mieux car la requete semble être lancée puisque la debugBar de symfony me montre le call aprés le click qui prend 15 secondes avant de finir sur une error 500 soit le temps normal du traitement quand cela aboutit à un succés

    Nom : error500.PNG
Affichages : 941
Taille : 112,2 Ko

    Toutefois cela finit quand même sur une erreur 500 sans que je ne sache pourquoi :/
    normalement quand je clique sur le lien de l'erreur en bas de la debugBar j'ai les détails mais là non :/

    une idée ?

Discussions similaires

  1. Quote dans une requete...
    Par Isildur dans le forum Langage SQL
    Réponses: 6
    Dernier message: 20/06/2006, 10h57
  2. [xsl]simuler le mecanisme OO de "liaison dynamique"
    Par philemon_siclone dans le forum XSL/XSLT/XPATH
    Réponses: 10
    Dernier message: 19/12/2003, 11h34
  3. Problème de quote
    Par kennini dans le forum ASP
    Réponses: 4
    Dernier message: 20/11/2003, 09h40
  4. VARCHAR contenant une quote '
    Par tonyskn dans le forum Langage SQL
    Réponses: 2
    Dernier message: 29/05/2003, 19h21
  5. Quotes dans TFilenameEdit (RXLib)
    Par AnnSo dans le forum Composants VCL
    Réponses: 3
    Dernier message: 23/01/2003, 20h26

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