View Full Version : [C++]Gestire Firefox
Ciao a tutti, non mettetevi a ridere per la mia domanda per favore perchè mi servirebbe proprio...:D
Ciò che vorrei fare io sarebbe poter gestire firefox con un programma in c++, in modalità nascosta o anche in modalità massimizzata...
Le funzioni che servirebbero a me sarebbero tipo:
-inserisci nello spazio di ricerca di google la stringa S
-aspetta che la pagina si carichi
-clicca il risultato n° 2
- quando si è caricato se il contenuto della pagina è uguale alla stringa X fai il refresh
Cose di questo tipo... Mi rivolgo a voi perchè non so proprio dove cercare, mi basterebbe di funzioni poi cerco di arrangiarmi io grazie infinite in anticipo... :D
ps. Andrebbero bene anche per internet explorer...o un qualsiasi browser per internet...
Quello che vuoi fare se non ho capito male è HTML scraping. Non serve controllare un browser per farlo, basta che usi una libreria che fa il parsing della pagina html, eventualmente la ripulisce e poi ti mette a disposizione un albero DOM da cui accedere comodamente ai dati.
Per fare queste cose mi trovo bene con Python e la libreria BeautifulSoup (http://www.crummy.com/software/BeautifulSoup/), piu o meno viene cosi il codice (molto semplice):
stringaDaCercare = "xxx"
numeroRisultato = 2
risultatiRicerca = BeautifulSoup("http://www.google.it/search?q=" + stringaDaCercare)
nodo = risultatiRicerca.html.body.div[3].div.ol.li[ numeroRisultato ].h3.a
link = nodo["href"].strip()
target = BeautifulSoup(link)
stringa = target.html.body.string.strip()
if stringa==stringaDaCercare: doSomething()
Il percorso alla riga 2 puoi ricavarlo usando l'estensione Firebug per Firefox, cliccando su 'analizza' e poi sull'elemento della pagina di cui vuoi ottenere il percorso.
Una volta l'ho fatto anche in C++ usando TidyLib (http://tidy.sourceforge.net/), è un po piu complesso pero.
scusami tanto ma io phyton non saprei neanke da dove iniziare... non è che c' è un alternativa per il c++? grazie mille...
Per C++ non so se ci sono librerie già pronte che fanno la stessa cosa, io mi ero fatto un parser usando TidyLib, si usa cosi:
Parser parser(fileName);
if (!parser.isValid()) return false;
// getText ritorna il testo contenuto nel nodo:
title = parser.getText("/html/body/div/table[2]/tr/td[2]/p/a/font/b/");
author = parser.getText("/html/body/div/table[2]/tr/td[2]/p/a[2]/font/b/");
description = parser.getText("/html/body/div/table[2]/tr/td[2]/p/");
// getValue ritorna il valore della proprieta specificata del nodo:
// (in questo caso è l'attributo HREF)
imageUrl = parser.getValue("/html/body/div/table[2]/tr/td[2]/a/", TidyAttr_HREF);
downloadUrl = parser.getValue("/html/body/div/table[2]/tr/td[2]/p/a/", TidyAttr_HREF);
qua c'è il codice della classe Parser, al posto di wxString puoi usare std::string se non usi wxWidget. per usarlo basta che includi il file parser.h nel tuo progetto e lo linki a tidylib.
#include <tidy.h>
#include <buffio.h>
#include <stdio.h>
#include <errno.h>
#include "wx/wx.h"
#include "wx/string.h"
class Parser {
TidyDoc tdoc;
bool valid;
bool walk(TidyNode ¤tNode, const char* tag, int pos);
void analizeToken(wxString &token, int &pos);
TidyNode getNode(wxString path);
public:
Parser();
Parser(const char* input);
bool open(const char* input);
wxString getValue(wxString path, TidyAttrId attr);
wxString getText(wxString path);
bool isValid() const;
~Parser();
};
Parser::Parser() {
valid=false;
}
Parser::Parser(const char* input) {
open(input);
}
bool Parser::open(const char* input) {
TidyBuffer output = {0};
TidyBuffer errbuf = {0};
int rc = -1;
Bool ok;
valid=false;
assert(input);
tdoc = tidyCreate(); // Initialize "document"
ok = tidyOptSetBool( tdoc, TidyXhtmlOut, yes ); // Convert to XHTML
if ( ok )
rc = tidySetErrorBuffer( tdoc, &errbuf ); // Capture diagnostics
if ( rc >= 0 )
rc = tidyParseString( tdoc, input ); // Parse the input
if ( rc >= 0 )
rc = tidyCleanAndRepair( tdoc ); // Tidy it up!
if ( rc >= 0 )
rc = tidyRunDiagnostics( tdoc ); // Kvetch
if ( rc > 1 ) // If error, force output.
rc = ( tidyOptSetBool(tdoc, TidyForceOutput, yes) ? rc : -1 );
if ( rc >= 0 )
rc = tidySaveBuffer( tdoc, &output ); // Pretty Print
if ( rc >= 0 )
valid=true;
else
valid=false;
tidyBufFree( &output );
tidyBufFree( &errbuf );
return valid;
}
bool Parser::isValid() const {
return valid;
}
Parser::~Parser() {
tidyRelease( tdoc );
}
TidyNode Parser::getNode(wxString path) {
TidyNode currentNode=tidyGetRoot(tdoc);
int initTag,endTag,pos;
wxString token;
initTag=1;
endTag=path.find('/',initTag);
while (endTag!=wxString::npos) {
token=path.substr(initTag,endTag-initTag);
if (token.IsEmpty()) continue;
analizeToken(token, pos);
if (!walk(currentNode, token.mb_str(),pos)) return 0;
initTag=endTag+1;
endTag=path.find('/',initTag);
char* name=(char*)tidyNodeGetName(currentNode);
}
return currentNode;
}
wxString Parser::getValue(wxString path, TidyAttrId attr) {
wxString result;
TidyNode currentNode=getNode(path);
if (currentNode)
result=wxString((char*)tidyAttrValue(tidyAttrGetById(currentNode, attr)), wxConvUTF8);
return result;
}
wxString Parser::getText(wxString path) {
TidyNode currentNode=getNode(path);
wxString result;
if (!currentNode) return result;
for (TidyNode child=tidyGetChild(currentNode); child; child=tidyGetNext(child)) {
if (tidyNodeIsText(child)) {
TidyBuffer buf={0};
tidyNodeGetText(tdoc, child, &buf);
result+=wxString((char*)buf.bp, wxConvUTF8);
}
}
return result;
}
void Parser::analizeToken(wxString &token, int &pos) {
int pqa=token.find('[');
int pqb=token.find(']');
pos=1;
if (pqa!=wxString::npos && pqb!=wxString::npos) {
wxString stringpos=token.substr(pqa+1,pqb-pqa-1);
pos=atoi(stringpos.mb_str());
token=token.substr(0,pqa);
}
}
bool Parser::walk(TidyNode ¤tNode, const char* tag, int pos) {
assert(tag);
assert(pos>=1);
int index=0;
TidyNode child;
for ( child = tidyGetChild(currentNode); child; child = tidyGetNext(child) ) {
char* name=(char*)tidyNodeGetName(child);
if (!name) continue;
if (!strcmp(name, tag)) index++;
if (index==pos) {
currentNode=child;
return true;
}
}
return false;
}
ok grazie infinite... ma scusa la mia ignoranza non ho ben capito quali sarebbero le funzioni da utilizzare con quel codice li... grazie infinite..:D
ok grazie infinite... ma scusa la mia ignoranza non ho ben capito quali sarebbero le funzioni da utilizzare con quel codice li... grazie infinite..:D
Metti che hai questa pagina html:
<html>
<title>Temperature></title>
<body>
<div>
<b>Citta</b><br>
<table>
<tr>
<td>Milano:</td>
<td>32</td>
</tr>
</table>
<...>
e vuoi scrivere del codice in C++ che legge la temperatura, fai cosi:
Parser parser( HMTLcode );
if (!parser.isValid()) return false;
string temperatura = parser.getText("/html/body/div/table/tr/td[2]");
cout << "La temperatura è: " << temperatura;
Invece getValue ritorna un attributo del nodo che ti serve.
Ad esempio se voglio ottenere l'attributo HREF di un tag <a> basta fare cosi:
string link = parser.getValue("/html/body/a", TidyAttr_HREF);
si ma io non conosco il codice della pagina da cui voglio prendere i dati...
è un :sofico: problema?
si ma io non conosco il codice della pagina da cui voglio prendere i dati...
è un :sofico: problema?
nel primo post avevi scritto:
Le funzioni che servirebbero a me sarebbero tipo:
-inserisci nello spazio di ricerca di google la stringa S
-aspetta che la pagina si carichi
-clicca il risultato n° 2
- quando si è caricato se il contenuto della pagina è uguale alla stringa X fai il refresh
per fare queste cose il codice ce l'hai a disposizione, basta che sul browser clicchi su visualizza codice html.
per trovare facilmente il percorso di quello che ti interessa all'interno del codice HTML complesso puoi usare il plugin FireBug che ti permette di analizzare il codice html con strumenti avanzati.
ahah... io non ne avevo idea che firefox avesse questa funzionalità.... fantastico... comunque ho provato il codice che hai postato su dev c++ e mi dice:
main.cpp:1:18: tidy.h: No such file or directory
main.cpp:2:20: buffio.h: No such file or directory
main.cpp:5:19: wx/wx.h: No such file or directory
main.cpp:6:23: wx/string.h: No such file or directory
main.cpp:9: error: `TidyDoc' does not name a type
main.cpp:12: error: expected `;' before '(' token
main.cpp:13: error: variable or field `analizeToken' declared void
main.cpp:13: error: expected `;' before '(' token
main.cpp:14: error: `TidyNode' does not name a type
main.cpp:19: error: `wxString' does not name a type
main.cpp:20: error: `wxString' does not name a type
main.cpp: In member function `bool Parser::open(const char*)':
main.cpp:33: error: `TidyBuffer' undeclared (first use this function)
main.cpp:33: error: (Each undeclared identifier is reported only once for each function it appears in.)
main.cpp:33: error: expected `;' before "output"
main.cpp:34: error: expected `;' before "errbuf"
main.cpp:36: error: `Bool' undeclared (first use this function)
main.cpp:36: error: expected `;' before "ok"
main.cpp:39: error: `assert' undeclared (first use this function)
main.cpp:41: error: `tdoc' undeclared (first use this function)
main.cpp:41: error: `tidyCreate' undeclared (first use this function)
main.cpp:42: error: `ok' undeclared (first use this function)
main.cpp:42: error: `TidyXhtmlOut' undeclared (first use this function)
main.cpp:42: error: `yes' undeclared (first use this function)
main.cpp:42: error: `tidyOptSetBool' undeclared (first use this function)
main.cpp:44: error: `errbuf' undeclared (first use this function)
main.cpp:44: error: `tidySetErrorBuffer' undeclared (first use this function)
main.cpp:46: error: `tidyParseString' undeclared (first use this function)
main.cpp:48: error: `tidyCleanAndRepair' undeclared (first use this function)
main.cpp:50: error: `tidyRunDiagnostics' undeclared (first use this function)
main.cpp:52: error: `TidyForceOutput' undeclared (first use this function)
main.cpp:54: error: `output' undeclared (first use this function)
main.cpp:54: error: `tidySaveBuffer' undeclared (first use this function)
main.cpp:60: error: `tidyBufFree' undeclared (first use this function)
main.cpp: In destructor `Parser::~Parser()':
main.cpp:68: error: `tdoc' undeclared (first use this function)
main.cpp:68: error: `tidyRelease' undeclared (first use this function)
main.cpp: At global scope:
main.cpp:70: error: `TidyNode' does not name a type
main.cpp:88: error: `wxString' does not name a type
main.cpp:96: error: `wxString' does not name a type
main.cpp:111: error: variable or field `analizeToken' declared void
main.cpp:111: error: `int Parser::analizeToken' is not a static member of `class Parser'
main.cpp:111: error: `wxString' was not declared in this scope
main.cpp:111: error: `token' was not declared in this scope
main.cpp:111: error: expected primary-expression before "int"
main.cpp:111: error: initializer expression list treated as compound expression
main.cpp:111: error: expected `,' or `;' before '{' token
main.cpp:122: error: `bool Parser::walk' is not a static member of `class Parser'
main.cpp:122: error: `TidyNode' was not declared in this scope
main.cpp:122: error: `currentNode' was not declared in this scope
main.cpp:122: error: expected primary-expression before "const"
main.cpp:122: error: expected primary-expression before "int"
main.cpp:122: error: initializer expression list treated as compound expression
main.cpp:122: error: expected `,' or `;' before '{' token
make.exe: *** [main.o] Error 1
Esecuzione terminata
In poche parole non ha le librerie... dove le potrei trovare? grazie ancora per il tuo aiuto
ps. In firefox dove sarebbe visualizza codice html??
ahah... io non ne avevo idea che firefox avesse questa funzionalità.... fantastico... comunque ho provato il codice che hai postato su dev c++ e mi dice:
In poche parole non ha le librerie... dove le potrei trovare? grazie ancora per il tuo aiuto
ps. In firefox dove sarebbe visualizza codice html??
Tuti i browser ti permettono di vedere il codice html della pagina che stai visualizzando! Su firefox devi premere Ctrl+U.
Per internet explorer invece c'è l'estensione HttpWatch simile a firebug.
Per compilare quel codice devi prima scaricare i sorgenti di TidyLib, compilarli e linkarli al tuo progetto.
Qua ci sono i link per il download e le istruzioni: http://tidy.sourceforge.net/libintro.html
Se conosci il C++ queste cose dovresti saperle fare, comunque se usi Visual C++ Express al posto di DevC++ è meglio, puoi scaricarlo gratis da qua: http://www.microsoft.com/express/vc/
Al posto di wxString usa std::string.
Alla funzione:
Parser parser( HMTLcode );
devi passare un array di char che contengono il codice HTML.
per ottenere dal tuo programma in C++ il codice html di una pagina web puoi usare Curl.
Scarichi i sorgenti da qua: http://curl.haxx.se/libcurl/ , li compili e li linki al to progetto.
Poi usa questa funzione per ottenere il codice:
char* codiceHTML = downloadFile("http://www.google.it/");
questo è il codice della funzione downloadFile::
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
#include <fstream>
struct MemoryStruct {
char *memory;
size_t size;
};
static void *myrealloc(void *ptr, size_t size)
{
if(ptr)
return realloc(ptr, size);
else
return malloc(size);
}
static size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
{
size_t realsize = size * nmemb;
struct MemoryStruct *mem = (struct MemoryStruct *)data;
mem->memory = (char*) myrealloc(mem->memory, mem->size + realsize + 1);
if (mem->memory) {
memcpy(&(mem->memory[mem->size]), ptr, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
}
return realsize;
}
char* downloadfile(const char* url) {
CURL *curl_handle;
struct MemoryStruct chunk;
chunk.memory=NULL; /* we expect realloc(NULL, size) to work */
chunk.size = 0; /* no data at this point */
curl_global_init(CURL_GLOBAL_ALL);
/* init the curl session */
curl_handle = curl_easy_init();
/* specify URL to get */
curl_easy_setopt(curl_handle, CURLOPT_URL, url);
/* send all data to this function */
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
/* we pass our 'chunk' struct to the callback function */
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
/* some servers don't like requests that are made without a user-agent
field, so we provide one */
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.3) Gecko/2008092510 Ubuntu/8.04 (hardy) Firefox/3.0.3");
/* get it! */
curl_easy_perform(curl_handle);
/* cleanup curl stuff */
curl_easy_cleanup(curl_handle);
/*
* Now, our chunk.memory points to a memory block that is chunk.size
* bytes big and contains the remote file.
*
* Do something nice with it!
*
* You should be aware of the fact that at this point we might have an
* allocated data block, and nothing has yet deallocated that data. So when
* you're done with it, you should free() it as a nice application.
*/
/* we're done with libcurl, so clean it up */
curl_global_cleanup();
return chunk.memory;
}
il vettore di char che ottieni contiene il codice HTML da passare al parser che ti ho messo nei post prima.
ok grazie infinite ho quasi capito tutto... però + di ogni altra cosa mi interessava una funzione in grado di far aspettare il programma finchè la nuova pagina web si fosse caricata... Non c' è qualche soluzione a questo?
ok grazie infinite ho quasi capito tutto... però + di ogni altra cosa mi interessava una funzione in grado di far aspettare il programma finchè la nuova pagina web si fosse caricata... Non c' è qualche soluzione a questo?
non so se ho capito bene, quando chiami:
char* codiceHTML = downloadFile("http://www.google.it/search?q=Windows");
il programma resta fermo la finche non ha scaricato tutto il codice HTML della pagina, per cui non serve che fai niente per aspettare.
Quella funzione infatti scarica solo il codice HTML, se invece ti serve scaricare delle immagini o altri file devi prima ottenere il link cosi:
string urlImmagine = parser.getValue("..percorso del tag <img>", TidyAttr_HREF);
e poi usare questa funzione per scaricare il file:
saveToFile("urlImmagine.c_str(), "C:\\immagine.jpg");
il codice è sto qua, va messo nel file assieme alla funzione downloadFile:
bool saveToFile(const char* url, char* destinationFile) {
char* value=downloadfile(url);
std::ofstream output(destinationFile, std::ios::out|std::ios::trunc);
if (!output) return false;
output << value.getptr();
output.close();
return true;
}
Comunque tutto il codice che ti ho passato l'avevo scritto facendo un collage di pezzi di codice presi da tutorial vari e sistemandolo alla buona.
Se vuoi usarlo davvero dovresti dargli una sistemata, soprattutto alla gestione dei puntatori.
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.