Načtení dat z webové stránky do pole   zodpovězená otázka

VB.NET

Potřebuji pravidelně stahovat z webu ČNB tabulku kůrzů měn do mé aplikace. V současnosti to řeším tak, že danou webovou stránku makrem otevřu v Excelu a data upravím a vyexportuji do txt souboru a s ním již pracuje moje aplikace. Ovšem toto řešení mi připadá nevhodné. Existuje nějaký elegantní způsob jak toto zpracování dat provést přímo ve vb.net aplikaci (data by putovala z webu do pole a pak by byla ukládána na disk).

Za případnou pomoc předem děkuji.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Taky bych to někdy využil, ale než nám někdo zkušený poradí, možná Vám pomůže to, co jsem nedávno spáchal já.

Potřeboval jsem pravidelně testovat parametry svého modemu (psou přístupné přes http:// stránku, takže si myslím, že by to mělo jít použít i na Váš problém.

Defacto jsem využil skutečnosti, že takovéto stránky jsou programově generované, což znamená hlavně to, že mají (alespoň v těch určitých partiích) přesnou neměnnou strukturu.

Takže udělám to, že:

1. Načtu předmětnou stránku

2. Převedu ji do řetězce

3. V řetězci vyhledám pozici určitého fragmentu textu, který mi na dané stránce přesně identifikuje místo, které mne zajímá a hlavně je stále neměnné.

4. od tohoto indexu pak přečtu obsah dat a dle konkrétní situace z něj vyseparuju případně přetypuju potřebná data.

Samozřejmě u mne to bylo celkem jednoduché - hledal jsem pouze asi 3 hodnoty, ale určitě by se to dalo rozšířit a zobecnit na libovolný případ, kdy daná stránka v oblasti dat, která mne zajímají, dodržuje stále stejnou strukturu.

Pokud chcete pro inspiraci, přidávám ten kousek kódu, který v mé aplikaci řešil právě tuto část (nebude-li Vám z něj něco jasné, klidně se zeptejte)(dávám to tak, jak to mám v aplikaci):

Public Function ParametryModemu() As String
        Dim stranka As String = ""
        Dim parametryStr As String = ""
        Dim indexStart, indexStop As Integer

        stranka = nactiStranku(My.Settings.adrModem & "/RgSignal.asp")

        If stranka = "" Then Return "MODEM NEODPOVÍDÁ! "
        If stranka.Substring(0, 5) <> "<html" Then Return stranka


        indexStart = stranka.IndexOf("<tr><td>Signal To Noise Ratio</td><td>") + 38
        indexStop = stranka.IndexOf("</td>", indexStart)
        parametryStr = "SNR: " & stranka.Substring(indexStart, indexStop - indexStart)

        indexStart = stranka.IndexOf("<tr><td>Power Level</td><td>", indexStop) + 28
        indexStop = stranka.IndexOf("<br>", indexStart)
        parametryStr &= " - DownPWR: " & stranka.Substring(indexStart, indexStop - indexStart)

        indexStart = stranka.IndexOf("<tr><td>Power</td><td>", indexStop) + 22
        indexStop = stranka.IndexOf("</td>", indexStart)
        parametryStr &= " - UpPWR: " & stranka.Substring(indexStart, indexStop - indexStart) & vbTab & vbTab

        Return parametryStr
    End Function

    Public Function nactiStranku(ByVal url As String) As String

        ' úprava adresy
        If url.Substring(0, 7) <> "http://" Then
            url = url.Insert(0, "http://")
        End If

        'vytvoření požadavku na stránku
        Dim req As Net.HttpWebRequest = CType(Net.WebRequest.Create(url), Net.HttpWebRequest)

        ' stažení stránky
        Dim resp As Net.HttpWebResponse

        Try
            resp = req.GetResponse()
        Catch ex As Net.WebException
            Return ex.Message
        End Try

        'převod stránky ze streamu do řetězce
        Dim reader As New IO.StreamReader(resp.GetResponseStream())
        nactiStranku = reader.ReadToEnd()
        reader.Close()
    End Function

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Dobrý den, nevím, jestli jsem našel správnou stránku, ale na webu ČNB nabízí i tabulku kurzů měn v textovém formátu:

http://www.cnb.cz/www.cnb.cz/cz/financni...

Stažení a načtení by mohlo vypadat třeba takto:

'stáhnout soubor
Dim url As String = String.Format("http://www.cnb.cz/www.cnb.cz/cz/financni_trhy/devizovy_trh/kurzy_devizoveho_trhu/denni_kurz.txt?date={0:dd.MM.yyyy}", Now)
My.Computer.Network.DownloadFile(url, "temp.txt", "", "", False, 10000, True)
'načíst soubor po řádcích
Using f As New IO.StreamReader("temp.txt")
    'přeskočit první dva řádky, je to záhlaví
    f.ReadLine()
    f.ReadLine()
    'číst až do konce souboru
    While Not f.EndOfStream()
        Dim p() As String = f.ReadLine().Split("|")
        Dim mena As String = p(3)       'získat kód měny
        'získat kurz měny (a vydělit je množstvím, u menších měn se udává kurz např. na 100 jednotek)
        Dim hodnota As Double = Double.Parse(p(4)) / Integer.Parse(p(2))
        'vypsat hodnotu do seznamu
        Dim li As New ListViewItem(mena)
        li.SubItems.Add(String.Format("{0:c4}", hodnota))
        ListView1.Items.Add(li)
    End While
End Using

nahlásit spamnahlásit spam 2 / 2 odpovědětodpovědět

Ha, ha, ha, - proč to dělat jednoduše, když to jde složitě, že?

Já si myslel, že snad ČNB by to mohla poskytovat i jinak (vždyť těch aplikací, které konkrétně tuto informaci využívají je tolik - třeba obyčejný účtní program), ale byl jsem líný se na jejich stránky kouknout - a radši jsem sepisoval, a sepisoval, a sepisoval .... :-)))

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Díky za náměty a rychlou reakci. Vyzkouším to.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Uvedené řešení je s funkční avšak toto konkrétní řešení vychází z

toho, že ČNB umožňuje stažení txt souboru tak je možné použít výše uvedenou metodu.

Chtěl jsem však se zeptat (tentokkrát čistě teoreticky) jak by vypadal kód pokud bych nějaká data potřeboval přímo z html stránky (když jsem zkusil do uvedeného řešení zadat URL html stránky tak to sice nezhavarovalo ale také to nic nenačetlo.

Za případnou reakci předem děkuji.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

V příkladu, který jsem (čistě prakticky) uvedl, tahám ta data přímo z html stránky. to první volání funkce:

...nactiStranku(My.Settings.adrModem & "/RgSignal.asp")

právě předává funkci "nactiStranku" URL stránky (v tomto případě mám v konfiguračním souboru aplikace uloženou proměnnou adrModem, což není nic jiného, než základní adresa mého modemu - mám ji jako IP adresu "http://xxx.xxx.xxx.xxx", ale může být libovolná, no a ten "/RgSignal.asp" je již konkrétní stránka, takže funkci předám korektní URL adresu "http://xxx.xxx.xxx.xxx/RgSignal.asp" a z této (HTTP) stránky čtu co potřebuji.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Použil jsem část vašeho kódu (viz. níže) a výsledkem je načítání jednotlivých řádků html kódu. Mým cílem bylo přečíst "jen" vystavené informace (jestli to je vůbec možné).

Dim req As Net.HttpWebRequest = CType(Net.WebRequest.Create("http://www.cnb.cz/www.cnb.cz/cz/financni_trhy/devizovy_trh/kurzy_devizoveho_trhu/denni_kurz.jsp"), Net.HttpWebRequest)
    Dim resp As Net.HttpWebResponse
    resp = req.GetResponse()

    'převod stránky ze streamu do řetězce
    Dim reader As New IO.StreamReader(resp.GetResponseStream())
    For i As Integer = 1 To 120
      Dim nactiStranku As String = reader.ReadLine()
      MsgBox(nactiStranku)
    Next

    reader.Close()
nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Já to právě ve svém příkladu řeším jinak.

do výstupu z funkce "načti stránku" dám celou stránku jako text:

nactiStranku = reader.ReadToEnd()

no a pak s tímto textem pracuji.

Vím že na mé stránce jsou hodnoty uloženy v tabulce s určitým popisem. Proto jsem si ze zdroje stránky vybral fragment textu, který je dostatečně reprezentativní, aby mi udal přesné místo v kódu:

indexStart = stranka.IndexOf("<tr><td>Signal To Noise Ratio</td><td>") + 38

Pak vím, že za tímto texttem jsou data, která mne zajímají (ta 38-čka je vlastně délka mého fragmentu, který hledám, abych četl až za ním.

No a konec mých dat je uzavřen koncem buňky tabulky. Proto najdu pozici nejbližšího konce buňky ZA mým bodem startu:

indexStop = stranka.IndexOf("</td>", indexStart)

no a pak je hledaná hodnota mezi nalezenými hranicemi:

parametryStr = stranka.Substring(indexStart, indexStop - indexStart)

Pak najdu další fragment textu, který je PŘED další hledanou hodnotou (hledám už od pozice posledního indexStopu, což zjednoduší vyhledávací řetězec), atd. atd.

Samozřejmě podmínkou je znát konkrétní skladbu prohledávané stránky, (ale na umělou inteligenci, která by sama obsah vyhodnotila a našla co chci - na to ještě nemám :-)


                        
                    
nahlásit spamnahlásit spam 0 odpovědětodpovědět

Na snadnou práci s HTML je lepší použít tzv. HTML parser, který stránku nejprve zpracuje a pak nám umožní přistupovat k jednotlivým tabulkám. Vydalo by to na celý článek. Na jednodušší stránky stačí funkce pro práci s řetězci, na složitější věci je lepší pužít parser.

V budoucnu budu psát článek o XML, práce s HTML je prakticky stejná, takže se to brzy dozvíte.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Už se těším(e)!

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback