3

首先,如果这是一个重复的问题,我很抱歉。我已经尝试了几个小时,我看到了 PHP 或其他语言的不同解决方案,但 R 没有。

我正在使用他们的 API 从 last.fm 网站检索数据。你确实需要一个 API 密钥来检索我想要获取的数据,但我会在这里让它变得更简单,希望你能回答我的问题。

这是我的问题:在某些时候,在检索数据时,我遇到了一个错误,它停止了我的请求。我跳过它一次,但它一次又一次地回来。我总是得到相同的结果:PCDATA invalid Char value #

这是一个例子:

string = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<lfm status=\"ok\">\n<results for=\"a\" xmlns:opensearch=\"http://a9.com/-/spec/opensearch/1.1/\">\n<opensearch:Query role=\"request\" searchTerms=\"a\" startPage=\"1382\" />\n<opensearch:totalResults>212588</opensearch:totalResults>\n<opensearch:startIndex>1381</opensearch:startIndex>\n<opensearch:itemsPerPage>1</opensearch:itemsPerPage><artistmatches>\n<artist>\n    <name>!B0A \0348E09;&gt;2</name>\n                <listeners>1672</listeners>\n                <mbid></mbid>\n                        <url>http://www.last.fm/music/!B0A+%1C8E09;%3E2</url>\n    <streamable>0</streamable>\n            <image size=\"small\">http://userserve-ak.last.fm/serve/34/88015017.png</image>\n        <image size=\"medium\">http://userserve-ak.last.fm/serve/64/88015017.png</image>\n        <image size=\"large\">http://userserve-ak.last.fm/serve/126/88015017.png</image>\n        <image size=\"extralarge\">http://userserve-ak.last.fm/serve/252/88015017.png</image>\n        <image size=\"mega\">http://userserve-ak.last.fm/serve/_/88015017/B0A+8E092+15286997.png</image>\n    </artist></artistmatches>\n</results></lfm>\n"

当我尝试解析此文本时,出现错误:

doc = xmlParse(string, asText = TRUE)
PCDATA invalid Char value 28
Error: 1: PCDATA invalid Char value 28

我相信导致这种情况发生的部分来自字符串的这一部分:

<name>!B0A \0348E09;&gt;2</name>\n 

但我现在不能确定。

我正在寻找的是这些解决方案之一,理想情况下是第一个,但其他任何一个都会让我高兴:

1 - 允许 R 接收这些无效字符

2 - 消除无效字符并继续解析而不停止。

3 - 跳过包含无效字符的字符串并继续解析

4 - 创建一个函数来查找无效字符,以便在从 last.fm 检索数据时包含它

我希望你能理解这个问题并帮助我。提前致谢

4

1 回答 1

0

你说的对。艺术家姓名包含用于 XML 解析的非法字符。

试试这个:

    illegal <- "[^\u0009\u000a\u000d\u0020-\uD7FF\uE000-\uFFFD]" 
    
    utf8_for_xml <- function(x) {
        
        return(gsub(illegal, "", x))
        
        }

    string_formatted <- utf8_for_xml(string)

    xmlParse(string_formatted)
<?xml version="1.0" encoding="utf-8"?>
<lfm status="ok">
  <results xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/" for="a">
    <opensearch:Query role="request" searchTerms="a" startPage="1382"/>
    <opensearch:totalResults>212588</opensearch:totalResults>
    <opensearch:startIndex>1381</opensearch:startIndex>
    <opensearch:itemsPerPage>1</opensearch:itemsPerPage>
    <artistmatches>
      <artist>
        <name>!B0A 8E09;&gt;2</name>
        <listeners>1672</listeners>
        <mbid/>
        <url>http://www.last.fm/music/!B0A+%1C8E09;%3E2</url>
        <streamable>0</streamable>
        <image size="small">http://userserve-ak.last.fm/serve/34/88015017.png</image>
        <image size="medium">http://userserve-ak.last.fm/serve/64/88015017.png</image>
        <image size="large">http://userserve-ak.last.fm/serve/126/88015017.png</image>
        <image size="extralarge">http://userserve-ak.last.fm/serve/252/88015017.png</image>
        <image size="mega">http://userserve-ak.last.fm/serve/_/88015017/B0A+8E092+15286997.png</image>
      </artist>
    </artistmatches>
  </results>
</lfm>

额外的:

让我们找出字符串对象中哪个字符对于 XML 是非法的。

函数gregexpr查找字符编号:

 gregexpr(illegal, string)
[1] 403
attr(,"match.length")
[1] 1

使用“Unicode”包:


require(Unicode)
unicode_string <- as.u_char(utf8ToInt(string))
unicode_string[403]

[1] U+001C


Unicode U+001C 是“信息分隔符四”,在 XML 中解析是非法的。

于 2021-12-15T04:06:52.550 回答