清理WordPress导出内容时,UTF-8中的字节序列无效

时间:2015-09-28 15:37:43

标签: ruby-on-rails ruby utf-8 nokogiri sanitize

我正在编写脚本以将WordPress内容导入我的Rails应用程序。我需要删除帖子正文中的所有图像。查看帖子时出现invalid byte sequence in UTF-8错误。

require 'action_view'
require 'nokogiri'
require 'sanitize'

namespace :wordpress do
  desc 'Import Worpress Posts'
  task import_posts: :environment do |_, _args|
    IMAGE_REGEX = /"([a-z\-_0-9\/\:\.]*\.(jpg|jpeg|png|gif))"/i
    user_id = User.first[:id]
    Blogit::Post.destroy_all
    File.open('lib/post.xml') do |file|
      items = Nokogiri::XML(file).xpath('//channel//item')
      items.each do |item|
        body = Sanitize.fragment(item.at_xpath('content:encoded').text).force_encoding('UTF-8')
               .encode('UTF-16', invalid: :replace, replace: '')
               .encode('UTF-8')

        begin
          post = Blogit::Post.create(
            title: item.at_xpath('wp:post_name').text.strip,
            body: body,
            blogger_id: user_id,
            bootsy_image_gallery: Bootsy::ImageGallery.create
          )
          images = item.at_xpath('content:encoded').text.scan(IMAGE_REGEX).map(&:first)
          post.save(validate: false)
          # post.update_column(:created_at, item.at_xpath('wp:post_date_gmt').text + ' +0000')
          # if images.any?
          #   images.each do |image|
          #     post.remote_feature_image_url = image.first
          #     post.bootsy_image_gallery.images << Bootsy::Image.create(remote_image_file_url: image.first)
          #   end
          #   post.save
          # end
        rescue StandardError => e
          puts "#{e}"
          next
        end
      end
    end
  end
end

此处抛出错误:

= content_tag(:article, id: "blog_post_#{post.id}", class: "blog_post") do

这是_post.html.slim:

= content_tag(:article, id: "blog_post_#{post.id}", class: "blog_post") do
  / Render the header for this blog post
  = render "blogit/posts/post_head", post: post

  / Render Post Image Slider
  / = render "blogit/posts/slider", images: post.bootsy_image_gallery.images if post.bootsy_image_gallery.images.any?

  / Render the body of this blog post (as Markdown)
  = render "blogit/posts/post_body", post: post

  / Render admin links to edit/delete this post
  = render "blogit/posts/post_links", post: post

  / Render info about the person who wrote this post
  = render "blogit/posts/blogger_information", post: post

  = render 'elements/tags', post: post

  / Render the no. of comments
  - if defined?(show_comments_count) and show_comments_count
    = render "blogit/posts/comments_count", post: post

2 个答案:

答案 0 :(得分:1)

您可以通过简单地调用MRI 2.1.0及其后续版本中存在的String#scrub#scrub!来删除非法字节。

body = Sanitize.fragment(item.at_xpath('content:encoded').text).force_encoding('UTF-8').scrub

不需要

.encode('UTF-16', invalid: :replace, replace: '').encode('UTF-8')

行。您正尝试执行scrub实际执行的操作,只需使用scrub即可。

这可以防止您获得异常,具体取决于实际引发异常的位置。你没有给我们一个例外的行号。您可能需要scrub从XML获取的其他数据,例如标题和图像。

它应该通过用Unicode替换字符()替换所有无效字节来防止异常。但是它是否是正确的解决方案取决于你的源文本发生了什么,为什么它的UTF-8字节无效。如果你在这里和那里只有一些,也许它只是有一些不好的字节。如果您发现所有或许多重音或非ASCII字符都替换为,那么您将不得不弄清楚编码被破坏的原因并正确修复它。

答案 1 :(得分:1)

你说你的错误是:

= content_tag(:article, id: "blog_post_#{post.id}", class: "blog_post") do

但是,此行甚至不会出现在您上面粘贴的源代码中。

如果错误确实被该行抛出,则表示您在post.id中有非法字节。这似乎不太可能。但如果你真的这样做了,你可以通过scrub post.id来解决'非法字节'异常......

content_tag(:article, id: "blog_post_#{post.id.scrub}", class: "blog_post") do

但这可能会导致进一步的问题。如果这确实是正在发生的事情,你必须首先弄清楚为什么post.id中存在非法字节,并解决潜在的问题。

但是,我持怀疑态度,我认为你没有准确地诊断哪一行引起了异常。

祝你好运。