Как извлечь Atom/RSS
-
21-09-2019 - |
Вопрос
Учитывая URL-адрес, если он имеет какие-либо узлы RSS, я добавляю его в базу данных.
например.:
Для этот URL, rssDoc.SelectNodes("rss/channel/item").Count
больше нуля.
Но для URL-адрес атома, rssDoc.SelectNodes("rss/channel/item").count
равен нулю.
Как я могу проверить, есть ли в URL-адресе Atom/RSS какие-либо узлы или нет?Я пытался rssDoc.SelectNodes("feed/entry").Count
, но дает мне нулевой счет.
Public Shared Function HasRssItems(ByVal url as string) As Boolean
Dim myRequest As WebRequest
Dim myResponse As WebResponse
Try
myRequest = System.Net.WebRequest.Create(url)
myRequest.Timeout = 5000
myResponse = myRequest.GetResponse()
Dim rssStream As Stream = myResponse.GetResponseStream()
Dim rssDoc As New XmlDocument()
rssDoc.Load(rssStream)
Return rssDoc.SelectNodes("rss/channel/item").Count > 0
Catch ex As Exception
Return False
Finally
myResponse.Close()
End Try
Конечная функция
Решение
Ваша основная проблема здесь в том, что XML-путь к узлу в этой строке:
Return rssDoc.SelectNodes("rss/channel/item").Count > 0
действителен только для RSS-каналы, нет АТОМ-каналы.
Один из способов преодолеть эту проблему в прошлом — использовать простую функцию для преобразования канала ATOM в канал RSS.Конечно, вы можете пойти другим путем или вообще не конвертировать, однако преобразование в единый формат позволяет вам написать один «общий» фрагмент кода, который будет извлекать различные элементы фида, которые могут вас заинтересовать. в (т.е.дата, название и т. д.)
Есть Статья о конвертере ATOM в RSS Однако в Code Project, который обеспечивает такое преобразование, то есть на C#.Ранее я сам вручную преобразовал это в VB.NET, поэтому вот версия VB.NET:
Private Function AtomToRssConverter(ByVal atomDoc As XmlDocument) As XmlDocument
Dim xmlDoc As XmlDocument = atomDoc
Dim xmlNode As XmlNode = Nothing
Dim mgr As New XmlNamespaceManager(xmlDoc.NameTable)
mgr.AddNamespace("atom", "http://purl.org/atom/ns#")
Const rssVersion As String = "2.0"
Const rssLanguage As String = "en-US"
Dim rssGenerator As String = "RDFFeedConverter"
Dim memoryStream As New MemoryStream()
Dim xmlWriter As New XmlTextWriter(memoryStream, Nothing)
xmlWriter.Formatting = Formatting.Indented
Dim feedTitle As String = ""
Dim feedLink As String = ""
Dim rssDescription As String = ""
xmlNode = xmlDoc.SelectSingleNode("//atom:title", mgr)
If xmlNode Is Nothing Then
This looks like an ATOM v1.0 format, rather than ATOM v0.3.
mgr.RemoveNamespace("atom", "http://purl.org/atom/ns#")
mgr.AddNamespace("atom", "http://www.w3.org/2005/Atom")
End If
xmlNode = xmlDoc.SelectSingleNode("//atom:title", mgr)
If Not xmlNode Is Nothing Then
feedTitle = xmlNode.InnerText
End If
xmlNode = xmlDoc.SelectNodes("//atom:link/@href", mgr)(2)
If Not xmlNode Is Nothing Then
feedLink = xmlNode.InnerText
End If
xmlNode = xmlDoc.SelectSingleNode("//atom:tagline", mgr)
If Not xmlNode Is Nothing Then
rssDescription = xmlNode.InnerText
End If
xmlNode = xmlDoc.SelectSingleNode("//atom:subtitle", mgr)
If Not xmlNode Is Nothing Then
rssDescription = xmlNode.InnerText
End If
xmlWriter.WriteStartElement("rss")
xmlWriter.WriteAttributeString("version", rssVersion)
xmlWriter.WriteStartElement("channel")
xmlWriter.WriteElementString("title", feedTitle)
xmlWriter.WriteElementString("link", feedLink)
xmlWriter.WriteElementString("description", rssDescription)
xmlWriter.WriteElementString("language", rssLanguage)
xmlWriter.WriteElementString("generator", rssGenerator)
Dim items As XmlNodeList = xmlDoc.SelectNodes("//atom:entry", mgr)
If items Is Nothing Then
Throw New FormatException("Atom feed is not in expected format. ")
Else
Dim title As String = [String].Empty
Dim link As String = [String].Empty
Dim description As String = [String].Empty
Dim author As String = [String].Empty
Dim pubDate As String = [String].Empty
For i As Integer = 0 To items.Count - 1
Dim nodTitle As XmlNode = items(i)
xmlNode = nodTitle.SelectSingleNode("atom:title", mgr)
If Not xmlNode Is Nothing Then
title = xmlNode.InnerText
End If
Try
link = items(i).SelectSingleNode("atom:link[@rel= alternate ]", mgr).Attributes("href").InnerText
Catch ex As Exception
link = items(i).SelectSingleNode("atom:link", mgr).Attributes("href").InnerText
End Try
xmlNode = items(i).SelectSingleNode("atom:content", mgr)
If Not xmlNode Is Nothing Then
description = xmlNode.InnerText
End If
xmlNode = items(i).SelectSingleNode("//atom:name", mgr)
If Not xmlNode Is Nothing Then
author = xmlNode.InnerText
End If
xmlNode = items(i).SelectSingleNode("atom:issued", mgr)
If Not xmlNode Is Nothing Then
pubDate = xmlNode.InnerText
End If
xmlNode = items(i).SelectSingleNode("atom:updated", mgr)
If Not xmlNode Is Nothing Then
pubDate = xmlNode.InnerText
End If
xmlWriter.WriteStartElement("item")
xmlWriter.WriteElementString("title", title)
xmlWriter.WriteElementString("link", link)
If pubDate.Length < 1 Then
pubDate = Date.MinValue.ToString()
End If
xmlWriter.WriteElementString("pubDate", Convert.ToDateTime(pubDate).ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss G\MT"))
xmlWriter.WriteElementString("author", author)
xmlWriter.WriteElementString("description", description)
xmlWriter.WriteEndElement()
Next
xmlWriter.WriteEndElement()
xmlWriter.Flush()
xmlWriter.Close()
End If
Dim retDoc As New XmlDocument()
Dim outStr As String = Encoding.UTF8.GetString(memoryStream.ToArray())
retDoc.LoadXml(outStr)
Return retDoc
End Function
Использование довольно простое.Просто загрузите свой канал ATOM в XmlDocument
объект и передайте его этой функции, и вы получите XmlDocument
объект обратно, в формате RSS!
Если вам интересно, я выложил целый Класс RSSReader на сайте Pastebin.com