Glengamoi (Forum) · AspHeute · .NET Heute (RSS-Suche) · AspxFiles (Wiki) · .NET Blogs

Webseiten automatisiert scrapen

Geschrieben von: Christian Holm
Kategorie: C#

This printed page brought to you by AlphaSierraPapa

Viele Webseiten bieten einen aktuellen Wetterbericht an. Um diesen für eigene Zwecke verwerten zu können, muß man die Webseite scrapen, aufparsen, und dann in das eigene Layout einbinden (rechtliche Probleme einmal dahingestellt). Allerdings ist es nicht klug, auf jeder eigenen Seite für jeden User neu zu scrapen - es reicht, dies automatisiert alle x Minuten oder Stunden zu machen, und den gescrapten Content in eine Datenbank zu schreiben.

Wir erledigen heute das Scrapen und Schreiben in die Datenbank mit Hilfe von C# bzw. dem .NET Framework und Scheduled Tasks - damit die Aktion auch automatisch abläuft. Dieser Artikel einer neuen Serie (Parsen, etc. folgt) zeigt Ihnen ein einfaches Beispiel, wie man die Sache angehen kann. Unser Projekt besteht der Einfachheit halber aus einer C# Kommandozeilenapplikation, welche die gescrapten Daten der Webseite mit den Wetterdaten in eine vorhandene SQL Datenbank schreibt.

Beginnen wir mit der Erstellung der Datenbank. Erstellen Sie im SQL Enterprise Manager eine Datenbank namens ScrapApp und eine Tabelle namens tContent, die folgende Struktur aufweist:

Da wir dies schnell erledigt haben, können wir uns nun den Beispiel-Sourcecode der Kommandozeilenapplikation ansehen. Diese in C# geschriebene Applikation (main.cs) besteht aus drei Klassen: Main, welche die Basisklasse darstellt und ScrapPage, welche von der Webseite den Content holt, sowie Write2DB, die den Content der Seite in die vorher erstellte SQL Datenbank schreibt.

Wie immer müssen wir am Anfang alle benötigten Namespaces referenzieren. In der Main Klasse deklariere ich die nötigen Variablen und führe die Methoden aus, die einerseits den Content scrapen (ScrapIt) bzw. den Content in die SQL Datenbank schreiben (WriteIt). Damit dies funktioniert, muß vorher natürlich eine Referenz auf die jeweilige Klasse erstellt werden:

using System;
using System.Net;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.IO;

class MainClass
{
	public static void Main()
	{
            string strURL = "http://prognoza.hr/jadran_e.html";
            string strContent,strErrCode;
            DateTime dtGrabTime;
            bool bSuccess;
            
            ScrapPage MyScrapPage = new ScrapPage();
            MyScrapPage.ScrapIt(strURL, out strContent, out strErrCode,out dtGrabTime);
            
            if("" == strErrCode)
            {
                bSuccess = true;
            }
            else
            {
                bSuccess = false;
            }       
            Write2DB MyWrite2DB = new Write2DB();
            MyWrite2DB.WriteIt(dtGrabTime, bSuccess, strContent,strErrCode);
	}
}

Der angegebene URL holt den Inhalt des Wetterberichts für die Adria. Die Stringvariable strContent repräsentiert den gescrapten Content der Webseite und die Stringvariable strErrCode enthält den eventuell anfallenden Fehlercode, wenn beim Scrapen etwas schief gelaufen ist. Die Variable dtGrabTime vom Datentyp DateTime ist die sogenannte Timestamp im Format yyyymmddhhmmss. Diese Timestamp bezieht sich auf das Zugriffsdatum und -zeit auf die Webseite. Die Variable bSuccess vom Typ bool ist ein Flag für den Erfolgstatus des Scrapens.

Bevor wir nun die Methode ScrapIt der Klasse ScrapPage aufrufen können, müssen wir hierfür ein neues Objekt erstellen. Die ScrapIt Methode hat als Eingabeparameter den URL der Webseite und gibt deren Inhalt, einen eventuellen Fehlercode des Scrapens und die Timestamp zurück:

class ScrapPage
{
	public void ScrapIt(string strUrl, out string strContent, 
                  out string strErrCode,out DateTime dtGrabTime)
	{
        strErrCode ="";
        WebRequest WebReq = WebRequest.Create(strUrl);
        WebResponse WebResp = WebReq.GetResponse();
        StringBuilder strBuildContent = new StringBuilder(); 
        dtGrabTime = DateTime.Now;
        
        try
        {
            StreamReader MyStrmR = new StreamReader(WebResp.GetResponseStream(), Encoding.ASCII);                    
            while (-1 != MyStrmR.Peek())
            {
                strBuildContent.Append(MyStrmR.ReadLine());
            }
        }
        catch (Exception e)
        {
            strErrCode = e.ToString();
        }
        strContent = strBuildContent.ToString();
	}
}

Wir erstellen zuerst einen WebRequest auf die angegebene URL und schreiben dann Zeile für Zeile (ReadLine Methode) den Inhalt der WebResponse bzw. des Streams in ein StringBuilder Objekt. Um eventuelle Fehler abzufangen ist dieser Code in einen try-Block gekapselt und mit Hilfe des catch Statements fangen wir die Exception ab. Um die Timestamp zu erhalten, verwenden wir die Now statische Eigenschaft der DateTime Structure.

Da wir nun den Content der Webseite, die Timestamp und hoffentlich keine Exception erhalten haben können wir die SQL Datenbank befüllen. Dies geschieht wie schon erwähnt mit der WriteIt Methode der Write2DB Klasse. Der Methode übergeben wir die gesammelten Daten (dtGrabTime, bSuccess, strContent, strErrCode) als Eingabeparameter:

class Write2DB
{
    public void WriteIt(DateTime dtGrabTime, bool bSuccess,string strContent,string strErrCode)
    {
    string strConn = "server=(local)\\NetSDK;database=ScrapApp;Trusted_Connection=yes";
    string insertCmd = "insert into tContent (GrabTime, Success, Content, ErrCode) values_
            (@GrabTime,@Success,@Content,@ErrCode)";
    
    SqlConnection MySqlConnection = new SqlConnection(strConn);
    SqlCommand MyCmd = new SqlCommand(insertCmd, MySqlConnection);

    MyCmd.Parameters.Add(new SqlParameter("@GrabTime", SqlDbType.DateTime, 8));
    MyCmd.Parameters["@GrabTime"].Value = dtGrabTime;
    MyCmd.Parameters.Add(new SqlParameter("@Success", SqlDbType.Bit, 1));
    MyCmd.Parameters["@Success"].Value = bSuccess;
    MyCmd.Parameters.Add(new SqlParameter("@Content", SqlDbType.NVarChar,4000));
    MyCmd.Parameters["@Content"].Value = strContent;
    MyCmd.Parameters.Add(new SqlParameter("@ErrCode", SqlDbType.NVarChar, 255));
    MyCmd.Parameters["@ErrCode"].Value = strErrCode;
    MyCmd.Connection.Open();
    MyCmd.ExecuteNonQuery();
    MyCmd.Connection.Close();
    }
}

Nach Bekanntgabe des Connectionstrings (strConn) zur SQL Datenbank ScrapApp legen wir noch das SQL INSERT Statement fest, welches die Daten dann einfügen wird. Nun können wir das Objekt für die SqlConnection erstellen und als Parameter den Connectionstring übergeben. Um die Daten einzufügen erstelle ich ein SqlCommand Objekt (MyCmd) das als Parameter hier das INSERT Statement und das SqlConnection Objekt übernimmt.

Nun wird die Datenreihe in Form einer Parametercollection übergeben, der zuerst das Datenbankfeld, der SqlDbType kompatible Datentyp und die Feldlänge übergeben wird. Schließlich erfolgen die einzelnen Wertübergaben aus den Variablen.

Jetzt ist es an der Zeit die Applikation zu kompilieren. Dies kann entweder durch Verwendung einer IDE geschehen oder durch Angabe von

csc /t:exe /out:ScrapApp.exe main.cs

bei der Kommandozeile. Was noch fehlt ist der Eintrag dieser Applikation in die Scheduled Task Liste, damit die Applikation täglich automatisch gestartet wird. Dazu öffen wir das Scheduled Tasks Applet in der Systemsteuerung und doppelkicken auf Add Scheduled Task. Es öffnet sich nun ein Wizard, dem wir zunächst die Applikations Informationen, wie Applikationsname und -pfad angeben. Da unsere Applikation nicht im System registriert ist, müssen wir mit Browse diese Angaben erstellen:

Nach der Angabe des Namens für den Eintrag in die Taskliste und die Vorauswahl für den Zeitpunkt des Startvorganges, geben wir im nächsten Schritt die genauen Angaben für den Startzeitpunkt unserer Applikation:

Im letzten Schritt müssen wir noch den Benutzer und sein zugehöriges Paßwort angeben, da die Applikation unter diesem ausgeführt wird. In der Taskliste scheint nun der Eintrag unser Appliaktion auf:

Schlußbemerkung

Damit "läuft" unser automatisierter Scrapvorgang, allerdings noch ohne visuellen Output für den Benutzer. In den weiteren Artikeln dieser Serie werden wir diese Applikation mit Funktionalität erweitern, bis wir den gefilterten Content dieser Webseite per SMS (Short Message Service) Nachricht verschicken.

This printed page brought to you by AlphaSierraPapa

Download des Codes

Klicken Sie hier, um den Download zu starten.
http://www.aspheute.com/code/20010910.zip

Verwandte Artikel

Kopieren verboten - Lizenzsicherung bei ASP Scripts
http:/www.aspheute.com/artikel/20020411.htm
Scrapen von Webseiten
http:/www.aspheute.com/artikel/20000824.htm
Siteüberwachung mit Scheduled Tasks
http:/www.aspheute.com/artikel/20010419.htm
Sonderzeichen korrekt grabben mit XmlHttp
http:/www.aspheute.com/artikel/20011113.htm
Webseiten automatisiert scrapen, Teil 2
http:/www.aspheute.com/artikel/20010911.htm
Wetterbericht per SMS versenden
http:/www.aspheute.com/artikel/20010913.htm

Links zu anderen Sites

Seewetterbericht Adria
http://prognoza.hr/jadran_e.html

 

©2000-2006 AspHeute.com
Alle Rechte vorbehalten. Der Inhalt dieser Seiten ist urheberrechtlich geschützt.
Eine Übernahme von Texten (auch nur auszugsweise) oder Graphiken bedarf unserer schriftlichen Zustimmung.