Question from .Net Tapuz forum: Using HttpWebRequest and HttpWebResponse with non-english content

שאלה:

אני משתמש בStreamReader כדי לקרוא את התוכן של דף Web. כלומר:

        Dim dataStream As Stream = m_response.GetResponseStream()
        Using reader As New StreamReader(dataStream, Text.Encoding.Default)
            Return reader.ReadToEnd()
        End Using

(הm_response הוא מסוג HttpWebResponse.)
הבעיה היא שכל עוד לא קראתי את תוכן הדף אני לא יכול לדעת באיזה קידוד הוא נשלח.
האם קיימת דרך לגלות באיזה קידוד הדף נמצא ולהמיר בהתאם?

 

תשובה:

 תשובתו של דניאל כץ.

מה שאנחנו למעשה רוצים לעשות כאן זה לקרוא את המידע עד הסוף מה-StreamReader ורק לאחר מכן לחפש בתוך התוכן ה-HTMLי ולראות מהו הקידוד של המסמך.

דבר ראשון ניתן לגשת HttpWebResponse.ContentEncoding שאמור לפרט מהו הקידוד של התוכן ה-HTMLי.
אך ייתכן והקידוד הזה יהיה ריק, אז במקרה הזה נפתח את מסמך ה-HTML ונחפש כותרות של Meta Data בתוך המסמך ה-HTMLי שבהן רשום קידוד הקובץ.

לאחר שהשגנו את הקידוד נשנה את קידוד המחרוזת המוחזרת בהתאם. 

זוהי דוגמה לשימוש הרצוי שלנו:

Sub Test()

Dim connection As New CWebConnection(New Uri("http://www.tapuz.co.il/"))
connection.SendRequest()

Dim distortedContent As String = connection.GetContent
Dim readableContent As String = connection.GetDecodedContent

End Sub

 וזוהי מחלקה שממשת את הדרישות והתהליך שתיארנו:

Public Class CWebConnection

Private m_request As HttpWebRequest
Private m_response As HttpWebResponse
Private m_content As String

 

Public Sub New(ByVal url As Uri)
    m_content = Nothing

    m_request = WebRequest.Create(url)
    m_request.Credentials = CredentialCache.DefaultCredentials
    m_request.Timeout = 30000
End Sub

 

Public Sub SendRequest()
    m_response = m_request.GetResponse()
End Sub

 

Public Function GetContent() As String
    If m_content = Nothing Then
        Dim dataStream As Stream = m_response.GetResponseStream()
        Using reader As New StreamReader(dataStream, Encoding.Default) 
            m_content = reader.ReadToEnd() + vbCrLf
        End Using
    End If

    Return m_content
End Function

 

Public Function GetDecodedContent() As String
    Dim raw As String = GetContent()
    Dim dest_enc As Encoding = GetEncoding()

    Return ConvertEncoding(raw, Encoding.Default, dest_enc)
End Function

 

Public Function GetEncoding() As Encoding
    Dim pattern As String = "<\s*(meta\s*http-equiv=\s*["']?)?content-type\s*[:"']?\s*(content\s*=\s*)?["']?\s*[\w/\\]*\s*;\s*charset\s*=\s*(?<encoding>[^"';>]*)\s*["']?\s*/?\s*>"
    Dim m_RegEx As Regex
    Dim encMatch As Match
    Dim enc As Encoding = Encoding.GetEncoding("windows-1255")

    If m_content = Nothing Then
        Throw New Exception("First call GetContent()")
    End If

    If GetEncodingHeader() IsNot Nothing Then
        Return GetEncodingHeader()
    Else
        m_RegEx = New Regex(pattern, RegexOptions.IgnoreCase Or RegexOptions.Compiled)
        encMatch = m_RegEx.Match(m_content)

        If encMatch.Success Then
            Try
                enc = Encoding.GetEncoding(encMatch.Groups("encoding").ToString.ToLower)
            Catch
            End Try
        End If
    End If

    Return enc
End Function

 

Public Function GetEncodingHeader() As Encoding
    Dim output As Encoding = Nothing
    If m_response.ContentEncoding <> "" Then
        Try
            output = Encoding.GetEncoding(m_response.ContentEncoding)
        Catch
            output = Nothing
        End Try
    End If

    Return output
End Function

 

Public Shared Function ConvertEncoding(ByVal raw As String, ByVal src_enc As Encoding, ByVal dest_enc As Encoding) As String
    Return src_enc.GetChars(Encoding.Convert(dest_enc, src_enc, src_enc.GetBytes(raw)))
End Function

End Class

קישור: http://www.tapuz.co.il/tapuzforum/main/Viewmsg.asp?forum=831&msgid=89155280

Published Sunday, November 19, 2006 9:00 PM by Justin-Josef Angel [MVP]

Comments

No Comments