Laden...

Automatisiert Webseiten aufrufen

Erstellt von Rastadisasta vor 16 Jahren Letzter Beitrag vor 16 Jahren 1.717 Views
R
Rastadisasta Themenstarter:in
13 Beiträge seit 2007
vor 16 Jahren
Automatisiert Webseiten aufrufen

Bin neu hier, daher Hallo erstmals.

Bevor ich das Problem schildere möchte ich generell den Zweck erklären.
Ich möchte einen kleinen Index von Gebrauchtwagen erstellen. Dazu hab ich mir gedacht ich beziehe jeden Tag von Webseiten die Autos aufgelistet haben den Webinhalt, filtere den und trage neue Autos in meine Datenbank ein. So sollten mal in einem ersten Schritt Daten von ungefähr 50 Weibseiten bezogen werden.

Nun zu meine leichten bis mittelschweren Problem.
Um zu den Seiten zu kommen auf denen die Inserate stehn sind immer gewisse Schritte notwendig. Einmal ist es möglich direkt die Seite aufzurufen. Manchmal müssen mittels POST oder GET zusätzlich Daten übertragen werden. Eine andere Variante ist dass eine Ids heraus gefiltet gehören die dann wieder z.B. post übertragen werden. Das Problem ist aber dass ich diese, bei jeder Seite unterschiedlichen Vorgehen nicht hardcoded in das Programm einbetten will. Da man leicht und einfach weiter Quellen eingeben sollte.

Eine Möglichkeit die mir eingefallen ist, die einzelnen Schritte in XML abzuspeichern und danach im Programm auszulesen und in Code umzusetzen.
Die feinste Variante wäre jedoch wenn ich dynamisch Code einbetten könnte. Also quasi unkompilierten Code der wie in eine Scriptsprache integriert wird.

Ist das Problem klar oder hab ich mich nicht ordentlich ausgedrückt. Was haltet ihr von der XML Lösung. Habt ihr andere Lösungsansätze?

Danke Danke Danke schon mal im Voraus

lG Jöhann

998 Beiträge seit 2007
vor 16 Jahren

Hmmm auch wenn der Ansatz gewagt ist und ich das Entwurfsmuster damit evtl. vergewaltige, wäre das Decorator-Muster dafür nicht ein Ansatz? Du könntest quasi deine Webseitenklasse mit den verschiedenen "Schritten" dekorieren und dann von außen nach innen ausführen... Das wäre nicht hartkodiert und du könntest später leicht neue Webseitenmuster zusammenbauen...

R
Rastadisasta Themenstarter:in
13 Beiträge seit 2007
vor 16 Jahren

Danke schon mal für die Antwort.
Also wirklich eine hoch interessante Idee. Zwar kannte ich das vorher nicht (Newbie) aber ich hab mich jetzt mal kurz eingelesen und muss sagen ein wirklich mächtiger Ansatz. Wobei ich auch gestehen muss für meine Anwendung jetzt wäre dieses Ding schon ziemlich verschärft. Aber ich werde mal überlegen wie ich das anwenden könnte.

Wie machen das eigentlich Andere die Informationen aus dem quasi deep-Web beziehen wollen. Die einfachste Idee meiner Seits wäre irgendwie dass ich einen Webbrowser in meine Applikation einbinden würde. Danach surfe ich die gewünschte Seite an und das Programm nimmt „einfach“ den gegangenen Weg, also die übertragenen Daten auf. Danach kann ich den Selben weg dann automatisiert zurücklegen. Okay klingt witzig aber wäre einfach.
Es kann doch nicht so schwierig sein eine Seite die man manuell ganz normal in einem Browser aufruft mittels eines Programms aufzurufen. Aber ich fürchte auch dass es das ist.

Ich wäre für alle weiteren Ideen wirklich dankbar

456 Beiträge seit 2007
vor 16 Jahren

Ich bin da auch gerade drannen mir was zu überlegen. Werde es aber ganz sicher in Datenbanktabellen (gegenwärtig fünf) verwalten und nach dem Laden auf Objekte mappen und die Collection (die Schritte) dann "abnavigieren". So zumindest stelle ich mir das vor. Eine Änderrung der Webseite gibt es ja immer mal, aber nicht jeden Tag und hierzu sollte dann lediglich eine Anpassung in der Datenbank ausreichen. Wohl gemerkt spreche ich jetzt NICHT vom Auslesen der Daten, sondern "nur" zum Navigieren der Zielseite (z.B. die Aktion Password ändern -> Step 1 anmelden -> 2 Menueintrag wählen -> Untermenueintrag wählen -> 4. Eingaben durchführen und bestätigen -> HInweismeldung suchen, dass Passwort erfolgreich geändert wurde -> 6. abmelden). Wobei hier Step 1 und 6 natürlich widerum unabhängig sein müssen, da diese auch von anderen Aktionen verwendet werden. Das lesen der Daten werde ich höchstwahrscheinlich, je nach Typ, mit Implementierten Interfaces machen - hier wäre aber auch Scripting-Code sinnvoll, gibt es sowas überhaupt. Kann man C#-Code z.B. in eine XML-Datei schreiben und dann in einem Programm parsen und interpretieren? Naja, in ein paar Tagen sind wir schlauer und ich hoffe, dass sich hier noch ein paar Ideengeber melden.

R
Rastadisasta Themenstarter:in
13 Beiträge seit 2007
vor 16 Jahren

Also...

Das Hauptproblem hab ich gelöst. Aber leider hat sich nun ein neues gebildet. Bitte aufmerksam machen falls ich dies in einen neuen thread posten soll.
Ich speichere die individuellen Vorgänge um Webseiten zu holen in XML ab. Das funktioniert recht gut und ist einfach zu administrieren.
Nun ist aber auf einer aspx seite ein Problem aufgetaucht.
In hiddenfields sind __VIEWSTATE und __EVENTVALIDATION gespeichert. Da sie dynamisch sind parse ich sie raus und setze sie danach in eine POST Anfrage wieder rein.
Aber dies Anfrage bringt danach nicht das gewünschte Ergebnis. Es könnte sein dass es sich dabei um ein Encoding Problem handelt aber da hab ich schon alles Mögliche ausprobiert.
Auch bin ich mir nicht sicher wie ich Leerzeichen über POST übertrage da sich in einigen Formularfelder auch solche befinden.
Mein http aufruf schau folgendermaßen aus. Vielleicht lässt sich dabei der Fehler ableiten.
In variable1 und variable2 sind die geparsten strings drinnen.

string poststring = __VIEWSTATE=variable1&automarke=audi&__EVENTVALIDATION=variable2
byte[] unicodeBytes = Encoding.Unicode.GetBytes(poststring);
byte[] buffer = Encoding.Convert(Encoding.Unicode, Encoding.ASCII, unicodeBytes);
HttpWebRequest m_WebReq = (HttpWebRequest)WebRequest.Create(url);
m_WebReq.Method = "POST";
m_WebReq.ContentType ="application/x-www-form-urlencoded";
m_WebReq.ContentLength = buffer.Length;
Stream PostData = m_WebReq.GetRequestStream();
PostData.Write(buffer, 0, buffer.Length);
PostData.Close();
m_WebReq.Timeout = 10000;
HttpWebResponse m_WebResp = (HttpWebResponse)m_WebReq.GetResponse();
Stream m_responsestream = m_WebResp.GetResponseStream();
StreamReader m_streamreader = new StreamReader(m_responsestream);
string web_content = m_streamreader.ReadToEnd();
m_streamreader.Close();

Für jede noch so kleine Hilfe wäre ich unendlich dankbar!!!

H
91 Beiträge seit 2007
vor 16 Jahren
  1. Encoding checken! Die POST daten müssen base64 encodiert sein. Damit erledigt sich das Leerzeichen Problem.

  2. _VIEWSTATE und _EVENT* variablen werden von ASP.NET Seiten dynamisch generiert. VIEWSTATE stellt die Konfiguration der Steuerelemente wieder her. Ob sie gebraucht werden, hängt davon ab, wie die Seite arbeitet. Meistens passiert ein Postback durch einen submit button. In diesem Fall muß der Wert dieses Buttons in den Post Daten sein! Die ASP-hidden fields kannst Du dann weglassen (versuchen).

  3. manchmal wird der Post string vor dem Postback noch mit Javascript aufbereitet. Eine "schlaue" Seite (welche verhindern will, daß eine Maschine mitliest) kann das benutzen, um automatisierte Anfragen zu erschweren. (Ist aber [noch] selten) Schau mal in den Quelltext der Seite, ob so was passiert.

  4. Was ist mit Session ID? Hast Du die erzeugen lassen? Kann auch entweder als Cookie vorliegen oder als hidden variable.

  5. Session Cookie(s) werden manchmal einfach so übertragen (in HTTP header) oder per javascript gesetzt. Erstere Variante kannst Du zusammen mit der Session ID kopieren.

  6. Benutze HTTP Monitor, um Deinen Post mit dem des Browsers zu vergleichen.

  7. (könnte man auch als 1) schreiben🙂 Ein paar Gedanken, was Du mit den Daten anstellen willst, können nicht schaden. Denn veröffentlichen würde ich das nciht einfach so! Ja, ja - Google macht das auch. Aber die haben ja auch entsprechende Anwaltsflotten...

==============================
heute schon numerics gehabt? Dann nichts wie
hin zu : ILNumerics.Net - numerics for .NET

H
91 Beiträge seit 2007
vor 16 Jahren

Was mir noch an Deinem Code auffällt:

m_WebReq.ContentType ="application/x-www-form-urlencoded";

... das ist ok. Aber oben encodierst Du Unicode. Dort sollte Base64 sein (= "urlencoded").

Alternativ: Hast Du mal daran gedacht, ein IE-Control zu benutzen und das fernzusteuern? Mittels mshtml kann man das sehr gut machen. Man kann auf buttons klicken lassen und JScript ausführen etc...

==============================
heute schon numerics gehabt? Dann nichts wie
hin zu : ILNumerics.Net - numerics for .NET

R
Rastadisasta Themenstarter:in
13 Beiträge seit 2007
vor 16 Jahren

Also wirklich danke für deine Antwort.
Das mit dem IE Control is wirklich hoch interessant. Werd das auf alle Fälle mal ausprobieren.
Bezüglich der Urheberrechte kann ich nur versichern dass ich mich im legalen Bereich bewege.
Aber das Encoding is wirklich ein Hund.
Wie würde denn der Code dann aussehen? Base64 steht mir nicht zuverfügung beim aufruf


byte[] buffer =  Encoding.ASCII.GetBytes(poststring);

Hatte mir vorgestellt dass statt ASCII eben BASE64 stehen muss, aber das is nicht vorhanden.
Die funktion

Convert.ToBase64String()

steht zu Verfügung. Aber ich check nicht wie ich das einbauen soll. Und vor allem wo.
Mit Thema Encoding hatte ich schon immer Schwierigkeiten.

lG Hansi

R
Rastadisasta Themenstarter:in
13 Beiträge seit 2007
vor 16 Jahren

HaHa, Habe soeben ein neuen Hinweis gefunden warums nicht funktioniert.

Die mit HTTP Monitor aufgezeichneten Daten unterscheiden sich wenn ich die Seite mit einem Browser und danach mit meinem Programm aufrufe. Im detail sind es die POST daten die unterschiedlich sind.

Mit Browser:

__VIEWSTATE=%2FwEPDwUKLTE5NDg5NTQ3Mg9kFgICA........

mit Programm:

__VIEWSTATE=**/**wEPDwUKLTE5NDg5NTQ3Mg9kFgICAw9.........

Also passt mein Encoding wirklich nicht ich verschicke ein / wobei es der Browser als %2F versendet.
Hoffe dass das der Fehler ist. Aber wie bessere ich diesen aus.
Ich hasse Ecoding!!! Hab ich das schon mal erwähnt?

H
91 Beiträge seit 2007
vor 16 Jahren

Versuch es mal hiermit:

        string buildPostData (Dictionary<string,string> namedValues) {
            if (namedValues == null) return ""; 
            StringBuilder sb = new StringBuilder(); 
            foreach (string key in namedValues.Keys) {
                if (sb.Length > 0)  sb.Append("&"); 
                sb.Append(s2base64(key));
                sb.Append("="); 
                sb.Append(s2base64(namedValues[key].ToString())); 
            }
            return sb.ToString(); 
        }
        string s2base64(string input) {
            // das hat nich funktioniert: 
            //byte[] tmp = Encoding.UTF8.GetBytes(input); 
            //return System.Convert.ToBase64String(tmp); 
            // .. aber das: 
            string ret = System.Web.HttpUtility.UrlEncode(
                        input,Encoding.GetEncoding("ISO-8859-15")); 
            return ret; 
        }

==============================
heute schon numerics gehabt? Dann nichts wie
hin zu : ILNumerics.Net - numerics for .NET

R
Rastadisasta Themenstarter:in
13 Beiträge seit 2007
vor 16 Jahren

Wirklich ein großes Dankeschön,hat mir wirklich vollkommen weitergeholfen.

Also die Variablennamen und die Variablen des Poststrings encodiere ich nach diesem Schema und es funktioniert einwandfrei.


System.Web.HttpUtility.UrlEncode(postvariable,Encoding.GetEncoding("ISO-8859-15"));

Zwar is mir net ganz klar warum ich diese dll extra einfügen muss aber was solls, es geht auf alle Fälle.

Übrigens kann ich die Variante mit XML wirklich nur empfehlen. Da kann man schnell und "einfach" neue Seiten einarbeiten.

Also nochmals vielen Dank für die Unterstützung !!!

H
91 Beiträge seit 2007
vor 16 Jahren

Vielleicht gibt es noch einen anderen Weg, ohne diesen Namespace. Wie es immer so ist - sobald es geht, hört man auf zu suchen... =)

==============================
heute schon numerics gehabt? Dann nichts wie
hin zu : ILNumerics.Net - numerics for .NET