CSV解析返回“未加引号的字段不允许\ r或\ n”,但是在源文件中找不到错误?

时间:2018-08-22 17:00:59

标签: ruby-on-rails ruby csv parsing error-handling

我在Ruby中为Rails应用程序使用内置的CSV函数。我正在调用URL(通过HTTParty)解析它,然后尝试将结果保存到我的数据库中。

问题是,我收到错误Unquoted fields do not allow \r or \n,该错误通常表示输入数据有问题,但是在检查数据时,我找不到任何问题。

这是我检索数据的方式:

response = HTTParty.get("http://" + "weather.com/ads.txt", limit: 100, follow_redirects: true, timeout: 10)

(此数据可从网址weather.com/ads.txt公开获得)

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

if response.code == 200 && !response.body.match(/<.*html>/) active_policies = []

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`

我有一些想法/调查结果:

  1. 我尝试逐行进行此操作,并且我已经确定134行是打破扫描的原因。我这样做是通过手动检查来实现的,如下所示: CSV.parse(response.body.lines[140..400].join("\n"), skip_blanks: true, skip_lines: /(^\s*#|^\s*$|^contact=|^CONTACT=|^subdomain=)/),但这无济于事,因为即使我将第134行标识为违规行,我也不知道如何检测或处理它。

    1. 我注意到源文件(在weather.com/ads.txt上)具有不寻常的字符,但是即使通过response.body.force_encoding("UTF-8")将其强制为utf-8仍然会引发错误。

    2. 我尝试将next添加到救援块,因此即使发现错误,它也将继续移动到csv中的下一行,但这不会发生-只是出错了并停止解析-因此我得到了前130个条目,但没有其余的条目。

    3. 类似于页面类型,我不确定页面类型是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

2 个答案:

答案 0 :(得分:2)

似乎发生了什么事,输入文件的行以\ n终止,除了第134和135行以\ r \ n终止。 CSV默认情况下将:row_sep设置为:auto,它将查看文件以确定最合适的分隔符,并选择了“ \ n”。这些多余的回车符使您认为您有一个多行字段,没有用引号引起来。

您可以通过以下方法解决此问题:在CSV文件到达之前先对其进行解析,然后删除\ r:

更改:

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

收件人:

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

答案 1 :(得分:2)

该文本中的行尾不一致,并且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

打开outputfile.txt并搜索\r个字符。尽管所有其他行仅以\n结尾,但我在行末仅找到其中的几个。