Ruby on rails CSV解析返回“;不带引号的字段不允许\r或\n;但是可以';在源文件中找不到错误?

Ruby on rails CSV解析返回“;不带引号的字段不允许\r或\n;但是可以';在源文件中找不到错误?,ruby-on-rails,ruby,csv,parsing,error-handling,Ruby On Rails,Ruby,Csv,Parsing,Error Handling,我正在为我的Rails应用程序使用Ruby中内置的CSV函数。我正在调用一个URL(通过HTTParty)对其进行解析,并试图将结果保存到我的数据库中 问题是,我得到的错误未加引号的字段不允许\r或\n,通常表明输入数据存在问题,但在检查数据时,我找不到任何问题 以下是我检索数据的方法: response=HTTParty.get(“http://“+”weather.com/ads.txt”,限制:100,跟随重定向:true,超时:10) (该数据可在url weather.com/ads.

我正在为我的Rails应用程序使用Ruby中内置的CSV函数。我正在调用一个URL(通过HTTParty)对其进行解析,并试图将结果保存到我的数据库中

问题是,我得到的错误
未加引号的字段不允许\r或\n
,通常表明输入数据存在问题,但在检查数据时,我找不到任何问题

以下是我检索数据的方法:

response=HTTParty.get(“http://“+”weather.com/ads.txt”,限制:100,跟随重定向:true,超时:10)

(该数据可在url weather.com/ads.txt上公开获取)

然后我尝试解析数据,应用一些正则表达式来忽略
之后的所有内容,忽略空行,等等

如果response.code==200&&!response.body.match(//)
现行政策=[]

CSV.parse(response.body, skip_blanks: true, skip_lines: /(^\s*#|^\s*$|^contact=|^CONTACT=|^subdomain=)/) do |row|
    begin
     #print out the individual ads.txt records 
     puts ""
     print row[0].downcase.strip + " " + row[1].strip + " " + 
     row[2].split("#").first.strip
            active_policies.push(
                publisher.policies.find_or_create_by(ad_partner: row[0].downcase.strip, external_seller_id: row[1].strip, seller_relationship: row[2].split("#").first.strip) do |policy|
                    policy.deactivated_at = nil
                end 
                )

                rescue => save
                #Add error event to the new sync status model
                puts "we are in the loop"
                puts save.message, row.inspect, save.backtrace
                    next
                end
                end
            #else
                #puts "Too many policies.  Skipping " + publisher.name
            #end
            #now we are going to run a check to see if we have any policies that are outdated, and if so, flag them as such.
            deactivated_policies = publisher.policies.where.not(id: active_policies.map(&:id)).where(deactivated_at: nil)
            deactivated_policies.update_all(deactivated_at: Time.now)
            deactivated_policies.each do |deactivated_policy|
                puts "Deactivating Policy for " + deactivated_policy.publisher.name
            end

         elsif response.code == 404 
            print 
            print response.code.to_s + " GET, "  + response.body.size.to_s + " body, "
            puts response.headers.size.to_s + " headers for " + publisher.name

         elsif response.code == 302
            print response.code.to_s + " GET, "  + publisher.name
         else 
            puts response.code.to_s +  " GET ads txt not found on " + publisher.name
         end

    publisher.update(last_scan: Time.now)

    rescue => ex
        puts ex.message, ex.backtrace, "error pulling #{publisher.name} ..." 
        #publisher.update_columns(active: "false")
    end
end`
我的一些想法/调查结果:

  • 我已经试着一行一行地看了一遍,我发现第134行破坏了扫描。为此,我进行了如下手动检查:
    CSV.parse(response.body.lines[140..400]。join(“\n”),skip_blanks:true,skip_lines:/(^\s*| ^ s*| ^ contact=| contact=| subdomain=)/)
    但这对我没有帮助,因为即使我将第134行识别为违规行,我也不知道如何检测或处理它

  • 我注意到源文件(位于weather.com/ads.txt)有不寻常的字符,但即使通过
    response.body.force_编码(“utf-8”)
    将其强制为utf-8,仍然会抛出错误

  • 我尝试将
    next
    添加到rescue块中,因此即使它发现错误,它也会移动到csv中的下一行,但这没有发生-它只是出错并停止解析-因此我得到了前130个条目,但没有剩下的条目

  • 与页面类型类似,我不确定页面类型是HTML而不是文本文件是否会在这里产生问题

  • 我很想知道如何检测和处理这个错误,所以这里的任何想法都是非常受欢迎的

    作为参考,
    #PBS
    显然是源文件中给我带来麻烦的第134行,但我不知道我是否完全相信这就是问题所在

    #canada
    
    google.com, pub-0942427266003794, DIRECT, f08c47fec0942fa0
    indexexchange.com, 184315, DIRECT
    indexexchange.com, 184601, DIRECT
    indexexchange.com, 182960, DIRECT
    openx.com, 539462051, DIRECT, 6a698e2ec38604c6
    
    #spain
    
    #PBS
    google.com, pub-8750086020675820, DIRECT, f08c47fec0942fa0
    google.com, pub-1072712229542583, DIRECT, f08c47fec0942fa0
    appnexus.com, 3872, DIRECT
    rubiconproject.com, 9778, DIRECT, 0bfd66d529a55807
    openx.com, 539967419, DIRECT, 6a698e2ec38604c6
    openx.com, 539726051, DIRECT, 6a698e2ec38604c6
    google.com, pub-7442858011436823, DIRECT, f08c47fec0942fa0
    

    看起来输入文件的行以\n结尾,但第134行和第135行以\r\n结尾除外。默认情况下,CSV的:row_sep设置为:auto,它查看文件以确定哪个分隔符最合适,并选择“\n”。这些额外的回车使它认为您有一个多行字段,它没有用引号封装

    您可以通过在CSV访问该文件之前预解析该文件并删除\r\n:

    更改:

    CSV.parse(response.body, skip_blanks: true, skip_lines: /(^\s*#|^\s*$|^contact=|^CONTACT=|^subdomain=)/) do |row|
    
    致:


    该文本中存在不一致的行尾,CSV解析器在这些行尾上遇到了障碍。一个非常快速的解决方法是删除所有
    \r
    字符,包括:

    response.body.gsub!("\r", '')
    
    如果您感到好奇,可以通过以下代码查看错误字符,该代码将每个字符的Ruby数组表示法写入文本文件:

    response = HTTParty.get("http://" + "weather.com/ads.txt", limit: 100, follow_redirects: true, timeout: 10)
    characters = response.chars.inspect
    output = File.open( "outputfile.txt","w" )
    output << characters
    output.close
    
    response=HTTParty.get(“http://“+”weather.com/ads.txt”,限制:100,跟随重定向:true,超时:10)
    characters=response.chars.inspect
    output=File.open(“outputfile.txt”、“w”)
    
    输出
    response.body.gsub!(“\r”,”)
    解决了它!我很好奇,outputfile.txt的位置在哪里?如果这是一个愚蠢的问题,我很抱歉,但我有另一个问题,我怀疑是同一个问题-我在第540行中得到了错误
    非法引用。
    对于techradar.com/ads.txt,我认为这里也有隐藏/错误字符,只是没有断行。另一个答案是@bkimble,使用
    tr()
    而不是
    gsub()
    ,对于这样的单个字符删除,这可能是更有效的选择。
    outputfile.txt
    将由该代码在Rails项目根目录中创建。您看到的行号540可能有点误导,因为CSV分配行号之前跳过了一些行号。非法报价实际上是在第580行:
    tremorhub.com,q017o-78mlk,经销商,1a4e959a1b50034a#高级视频点播又名“Telaria”
    好的,我将更改为使用
    tr()
    -为了避免“Telaria”问题,我会通过regex控制报价吗?我想,你可以。您还可以使用
    tr()
    gsub()
    删除所有引号特许。尽管其中任何一个都可能很混乱,因为引号在.csv文件中也是合法的分隔符,只是在本文件中没有使用。我注意到给您带来麻烦的引号出现在您要删除的
    后面的文本中。但是,您要在CSV解析行之后删除它。考虑预先移除它。
    response = HTTParty.get("http://" + "weather.com/ads.txt", limit: 100, follow_redirects: true, timeout: 10)
    characters = response.chars.inspect
    output = File.open( "outputfile.txt","w" )
    output << characters
    output.close