3 votes

Téléchargement en masse de pages web à l'aide de Qt

Je veux écrire un programme utilisant Qt qui télécharge un grand nombre de pages web HTML, environ 5000, à partir d'un site chaque jour. Après avoir téléchargé ces pages, j'ai besoin d'extraire certaines données en utilisant DOM Query, en utilisant le module WebKit, et ensuite de stocker ces données dans une base de données.

Quelle est la meilleure/la plus correcte/la plus efficace façon de procéder, en particulier pour la phase de téléchargement et d'analyse ? Comment gérer ce nombre de demandes et comment créer le "gestionnaire de téléchargement" ?

2voto

PiedPiper Points 3595

Pour télécharger les pages, il est judicieux d'utiliser une bibliothèque spécialisée telle que libcurl

1voto

Jeffrey Holmes Points 47

La réponse a déjà été donnée, mais voici une solution qui utilise ce que vous avez demandé, à savoir faire cela avec QT.

Vous pouvez créer un (Website Crawler) en utilisant QT (spécifiquement QNetworkManager, QNetworkRequests, QNetworkReply). Je ne sais pas exactement si c'est la bonne façon de gérer une telle tâche, mais j'ai trouvé qu'en utilisant plusieurs threads, vous pouvez maximiser l'efficacité et gagner du temps. (Quelqu'un peut me dire s'il y a une autre façon de faire / ou confirmer si c'est une bonne pratique)

Le concept est qu'une liste de travail est mise en attente et qu'un travailleur effectue le travail et, après avoir reçu l'information/le html, le traite et passe ensuite à l'élément suivant.

Classe d'objet travailleur Classe qui accepte une url, traite et télécharge les données html de l'url, puis traite l'information lorsqu'elle est reçue.

Créer une file d'attente et un gestionnaire pour la file d'attente J'ai créé une QQueue< QString> urlList pour contrôler le nombre d'éléments simultanés traités et la liste des tâches à accomplir.

    QQueue <String> workQueue; //First create somewhere a 
    int maxWorkers = 10;

    //Then create the workers
    void downloadNewArrivals::createWorkers(QString url){
checkNewArrivalWorker* worker = new checkNewArrivalWorker(url);
workQueue.enqueue(worker);
}

    //Make a function to control the amount of workers, 
    //and process the workers after they are finished

    void downloadNewArrivals::processWorkQueue(){
if (workQueue.isEmpty() && currentWorkers== 0){
    qDebug() << "Work Queue Empty" << endl;
} else if (!workQueue.isEmpty()){
    //Create the maxWorkers and start them in seperate threads
    for (int i = 0; i < currentWorkers && !workQueue.isEmpty(); i++){
        QThread* thread = new QThread;
        checkNewArrivalWorker* worker = workQueue.dequeue();
        worker->moveToThread(thread);
        connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
        connect(thread, SIGNAL(started()), worker, SLOT(process()));
        connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
        connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
        connect(thread, SIGNAL(finished()), this, SLOT(reduceThreadCounterAndProcessNext()));
        connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
        thread->start();
        currentWorkers++;
    }
}
}

    //When finished, process the next worker
    void downloadNewArrivals::reduceThreadCounterAndProcessNext(){
currentWorkers--;  //This variable is to control amount of max workers

processWorkQueue();
    }

    //Now the worker
    //The worker class important parts..
    void checkNewArrivalWorker::getPages(QString url){
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
QNetworkRequest getPageRequest = QNetworkRequest(url); //created on heap 
getPageRequest.setRawHeader( "User-Agent", "Mozilla/5.0 (X11; U; Linux i686 (x86_64); "
                           "en-US; rv:1.9.0.1) Gecko/2008070206 Firefox/3.0.1" );
getPageRequest.setRawHeader( "charset", "utf-8" );
getPageRequest.setRawHeader( "Connection", "keep-alive" );
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyGetPagesFinished(QNetworkReply*)));
connect(manager, SIGNAL(finished(QNetworkReply*)), manager, SLOT(deleteLater()));
manager->get(getPageRequest);
}

    void checkNewArrivalWorker::replyGetPagesFinished(QNetworkReply *reply){
QString data = reply->readAll(); //Here data will hold your html to process as needed...
reply->deleteLater();
emit finished();

}

Après avoir obtenu vos informations, je me suis contenté de traiter les informations à partir d'une QString, mais je suis sûr que vous pourrez trouver comment utiliser un parseur DOM une fois que vous aurez atteint ce stade.

J'espère que cet exemple est suffisant pour vous aider.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X