Jag har ett litet program som hämtar börskurser från nätet. Det är flera sidor som jag går in på och den info som jag är intresserad av finns i början av sidan. Nu tänkte jag ev. använda min bärbara dator och Vodafones 3G kort för att hämta informationen. Om du läser av en ström med data genom en socket så kan du avsluta läsningen när du vill... Jag har tidigare här på pellesoft fått hjälp med denna kod i inlägget (MSHTML Ok, det ska nog gå med den metoden också men det du kan göra är att använda sockets istället. En liten sak bara, SAX informationen finns ju nästan längst ner i källkoden på sidan du vill hämta så det finns ingen större nytta med att begränsa ner hur mycket du hämtar... Följande laddar ner en HTML sidan genom att använda sockets... Är på jobbet nu men ska läsa och försöka förstå koden i helgen. Det finns ett kommando man kan skicka med i requesten (huvudet) som heter Range, men jag har inte testat det speciellt mycket. Det jag har testat så har jag inte fått det att fungera, och om det fungerar eller inte beror på om servern man frågar av stödjer kommandot... Jag är mest nyfiken för min egen del och se om jag kan få det att fungera, för ju mindre data man behöver hämta dessto bättre och det gäller ju i alla fall när man bara är intresserad av en liten bit =) Range ska nog fungera. Vet att t.ex. flashget använder det när den kör http. Där har du lite fel Onkelborg... Posta gärna länkar till alla sidor som du vill hämta ut från och vad du vill hämta ut från dem så kan jag hjälpa dig att få en smart lösning på problemet. Nu har jag kommit på hur du verkligen kan slippa ladda ner så mycket data... Tackar tackar =) Vet inte hur man gör. Ja återkommer när jag hinner. Problemen och lösningarna hopar sig i stora högar just nu.Internet & 3G
Då är frågan: Kan man avbryta läsningen från en sida när man är nöjd s.a.s.? Om jag har den info jag vill ha efter kanske 20% av hela sidan så vill jag inte betala för resten givetvis. Egentligen borde jag inte gå på detta så länge det inte finns ett alternativ med ett fast pris, men pga nyhetens behag är nog risken stor att det tar lång tid innan vi är där. Vad säger ni, går det att lösa på något sätt?
mvh OlaSv: Internet & 3G
Hur hämtar du ner datat?
Mvh,
ThomasSv: Internet & 3G
2004-05-14 07:11:25 - Ola Ljungcrantz), och det är den jag har byggt vidare på.
Private Function GetSAX() As Double
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US")
Dim url As String = "http://www.nordnet.se"
Dim objRequest As WebRequest = WebRequest.Create(url)
Dim objResponse As WebResponse = objRequest.GetResponse()
Dim oSR As StreamReader = New StreamReader (objResponse.GetResponseStream())
Dim strContent As String = oSR.ReadToEnd()
'odynamisk lösning som kräver att sidan inte ändrar på sig...
Dim pos As Integer = strContent.IndexOf("alt=""SAX""") 'hitta taggen ovanför sax-td
If pos > -1 Then
'OBS ingen error hantering... egentligen borde man kolla att all info är rätt och att pos inte är -1
pos = strContent.IndexOf("<td", pos) 'hämta positionen för nästa tagg...
pos = strContent.IndexOf(">", pos) 'hämta slutet på taggen
Dim end As Integer = strContent.IndexOf("<", pos += 1) 'hämta positionen för nästa tagg
Dim sax As String = strContent.Substring(pos, end - pos) 'hämta det mellan taggarna
sax = System.Web.HttpUtility.HtmlDecode(sax) 'städa html
Return Double.Parse(sax.Trim()) 'parsa till en double
Else
Return -1
End If
End Function
//OlaSv: Internet & 3G
En request till en webserver är inte speciellt svår att göra och du har full kontroll över hur mycket data du tankar ner.
Och istället för att använda IndexOf etc för att hitta datat du vill ha kan du köra med Regular Expressions.
Jag hjälper dig gärna, ska ta fram lite kod som jag skrivit...
Mvh,
ThomasSv: Internet & 3G
Men var det bara ett exempel på en sida, du sa att du hämtar från flera?
Mvh,
ThomasSv: Internet & 3G
<code>
Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports System.Text.RegularExpressions
Public Shared Function GetSource(ByVal Address As String) As String
Dim Socket As Socket
Socket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
Dim Match As Match
Match = Regex.Match(Address, "^(?:http://)?(?<host>(?:www\.)?[^/]*)(?<rest>.*)$")
If Match.Success Then
Socket.Connect(New IPEndPoint(Dns.Resolve(Match.Groups("host").Value).AddressList(0), 80))
Else
Return Nothing
End If
If Socket.Connected Then
Dim Command As String
Command = "GET " + IIf(Match.Groups("rest").Value.Trim.Length > 0, Match.Groups("rest").Value.Trim, "/") + " HTTP/1.1" + vbCrLf
Command += "User-Agent: Mozilla/4.0" + vbCrLf
Command += "Host: " + Match.Groups("host").Value + vbCrLf
Command += "Connection: close" + vbCrLf
Command += vbCrLf
Socket.Send(Encoding.Default.GetBytes(Command), Command.Length, SocketFlags.None)
Dim Buffer(511) As Byte
Dim receivedBytes As Integer
Dim Response As New StringBuilder("")
Try
Do
receivedBytes = Socket.Receive(Buffer)
Response.Append(Encoding.Default.GetString(Buffer, 0, receivedBytes))
'Här lägger du in kontrollen om du har fått all data du vill ha och avslutar loopen om så är fallet
If Response.ToString.IndexOf("</html>") > 0 Then Exit Do
Loop
Socket.Shutdown(SocketShutdown.Both)
Socket.Close()
Return Response.ToString
Catch ex As Exception
Socket.Shutdown(SocketShutdown.Both)
Socket.Close()
Return Nothing
End Try
Else
Socket.Shutdown(SocketShutdown.Both)
Socket.Close()
Return Nothing
End If
End Function
</code>
Men som sagt, om datat du vill hämta är långt ner i källkoden tjänar man inte speciellt mycket...
Mvh,
ThomasSv: Internet & 3G
Jo, det var bara ett exempel. Den info jag vill åt ligger ungefär mitt på sidan tror jag. Det hade ju varit förnämt om man kunde börja läsa mitt i också…….(?)
Du ska ha ett stort tack för hjälpen Thomas! Jag återkommer med ev. frågor efter helgen.
MVH
OlaSv: Internet & 3G
Men gör en sökning på t.ex. "HTTP Range" eller liknande, du kanske kan få det att fungera...
Enda du ska behöva göra är att lägga till något i stil med "Range: 100-300" på en egen rad i huvudet som skickas vid requesten...
Jag tror jag ska kika vidare på det när jag får tid, har lite ärenden att uträtta just nu men kanske ikväll...
Mvh,
ThomasSv: Internet & 3G
Mvh,
ThomasSv: Internet & 3G
Range: StartByte-[SlutByte]
Det som står inom [] är frivilligt (enlgit flashget iaf.)Sv: Internet & 3G
Det ska vara följande: Range: bytes=[Startoffset]-[Stopoffset]
Det kan se ut ungefär såhär: Range: bytes=100-199
Eller såhär: Range: bytes=-99
Eller såhär: Range: bytes=100-
Eller såhär: Range: bytes=0-99,200-299
Första ska hämta ut byten 100-199, alltså en längd på 200 byte
Andra hämtar ut 0-99, alltså 100 byte
Tredje hämtar ut allt förrutom de första 100 byten
Fjärde ska hämta ut 0-99, 100 byte + 200-299, 100 byte = 200 byte totalt...
Alla servrar stödjer dock inte Range men en av de du vill hämta från Ola stödjer det, nämligen http://www.nordnet.se =)
Så du kan minska ner mängden data du hämtar från ca 36000 till enbart 200 byte...
Dock måste koden jag postade tidigare ändras lite så den blir lite stabilare, men jag har en fungerande version redan.
Mvh,
ThomasSv: Internet & 3G
Jag tror man måste kartlägga vilka som stödjer Range metoden och vilka som inte gör det, sedan har man två olika metoder som hämtar data... En av metoderna använder sig av Range och den andra kan man begränsa i kod hur mycket data den ska ladda ner.
Sen måste man ju vara beredd på att sidorna ändras hela tiden, så man måste göra en smart lösning för att kompensera för det också.
Jag föreslår att man sparar index värden som man senast använde för att ladda ner dokumentet och finns informationen inte med när man laddar ner med till exempel Range får man uppdatera indexvärdena genom att ladda ner lite mer tills man kan lokalisera datat, med fördel använder man Regular Expressions...
När det är klart har man sitt på det torra fram tills datamänden före det man vill ha ut ändras drastiskt...
Lite spekulationer, men det går helt klart att få att fungera...
Kanske du bjuder på kaffe sedan när du blir miljonär ;)
Mvh,
ThomasSv: Internet & 3G
Om du kan ha en ASP.NET sida som du kan anropa så behöver den bara rentunera allting i ett lätthanterligt format, och det är alltså så lite data som du totalt kan ladda ner...
Blev nog lite luddigt det där, men tänk dig att du har alla funktioner som hämtar data på en ASP.NET sida och där skriver du bara ut datat, till exempel så är varje sida avskilt med en radbrytning och varje värde på varje sida är avskilt med en tab...
Då kan du få all data med ett enda anrop, allting går fort för det är servern med dess snabba lina som gör anropen och du laddar bara ner den data du vill betala för...
Mvh,
ThomasSv: Internet & 3G
Har du möjlighet att ha en sådan sida någonstans då?
Mvh,
ThomasSv: Internet & 3G
mvh Ola