রুবি 1.9: ইউটিএফ -8 এ অবৈধ বাইট অনুক্রম


109

আমি রুবিতে একটি ক্রলার লিখছি (1.9) যা এলোমেলো সাইট থেকে প্রচুর এইচটিএমএল গ্রহণ করে।
লিঙ্কগুলি নিষ্কাশনের চেষ্টা করার সময়, আমি ঠিক করেছি .scan(/href="(.*?)"/i)নোকোগিরি / এইচপ্রিকোট (মেজর স্পিডআপ) এর পরিবর্তে কেবল ব্যবহার করার সিদ্ধান্ত নিয়েছি । সমস্যাটি হ'ল আমি এখন প্রচুর invalid byte sequence in UTF-8ত্রুটি পেয়েছি ।
আমি যা বুঝতে পেরেছি তা থেকে, net/httpগ্রন্থাগারের কোনও এনকোডিং নির্দিষ্ট বিকল্প নেই এবং যে জিনিসগুলি আসে তা মূলত সঠিকভাবে ট্যাগ হয় না।
প্রকৃতপক্ষে আগত ডেটার সাথে কাজ করার সর্বোত্তম উপায় কী হবে? আমি .encodeপ্রতিস্থাপন এবং অবৈধ বিকল্পগুলি সেট করে চেষ্টা করেছি , তবে এখন পর্যন্ত কোনও সাফল্য নেই ...


অক্ষরগুলি ভেঙে দিতে পারে এমন কিছু, তবে অন্যান্য লাইব্রেরির জন্য স্ট্রিংকে বৈধ রাখে: বৈধ_আরক্ষক = অবিশ্বস্ত_স্তর.আনপ্যাক ('সি *') pack প্যাক ('ইউ *')
মার্ক সিগার

সঠিক সমস্যাটি রয়েছে, একই অন্যান্য সমাধানগুলির চেষ্টা করে। ভালোবাসা নেই। মার্কের চেষ্টা করা হয়েছে, তবে মনে হচ্ছে এটি সবকিছু ছাপিয়ে গেছে। আপনি কি নিশ্চিত যে 'U*'পূর্বাবস্থায় ফিরে এসেছেন 'C*'?
জর্দান ফিল্ডস্টাইন

না, এটি করে না :) আমি কেবলমাত্র এটি এমন একটি ওয়েবক্লোলারে ব্যবহার করেছি যেখানে আমি তৃতীয় পক্ষের লাইব্রেরিগুলিকে যত্ন করি যেখানে আমি এখানে এবং সেখানে একটি বাক্য সম্পর্কে বেশি ক্র্যাশ করি না।
মার্ক সিগার

উত্তর:


172

রুবি ১.৯.৩ এ অবৈধ ইউটিএফ -8 সিকোয়েন্সগুলি "উপেক্ষা" করার জন্য স্ট্রিং.ইনকোড ব্যবহার করা সম্ভব। এখানে একটি স্নিপেট রয়েছে যা 1.8 ( আইকনভি ) এবং 1.9 ( স্ট্রিং # এনকোড ) উভয় ক্ষেত্রেই কাজ করবে :

require 'iconv' unless String.method_defined?(:encode)
if String.method_defined?(:encode)
  file_contents.encode!('UTF-8', 'UTF-8', :invalid => :replace)
else
  ic = Iconv.new('UTF-8', 'UTF-8//IGNORE')
  file_contents = ic.iconv(file_contents)
end

বা যদি আপনার সত্যিই সমস্যা হয় তবে আপনি ইউটিএফ -8 থেকে ইউটিএফ -16 এবং ইউটিএফ -8 এ ফিরে যেতে ডাবল রূপান্তর করতে পারেন:

require 'iconv' unless String.method_defined?(:encode)
if String.method_defined?(:encode)
  file_contents.encode!('UTF-16', 'UTF-8', :invalid => :replace, :replace => '')
  file_contents.encode!('UTF-8', 'UTF-16')
else
  ic = Iconv.new('UTF-8', 'UTF-8//IGNORE')
  file_contents = ic.iconv(file_contents)
end

3
কিছু সমস্যাযুক্ত ইনপুট দিয়ে আমি ইউটিএফ -8 থেকে ইউটিএফ -16 এবং তারপরে ইউটিএফ -8 এ ডাবল রূপান্তর ব্যবহার করি file_contents.encode!('UTF-16', 'UTF-8', :invalid => :replace, :replace => '') file_contents.encode!('UTF-8', 'UTF-16')
রুবেনলগুনা

7
এর বিকল্পও রয়েছে force_encoding। আপনার যদি কোনও ইউটিএফ -8 হিসাবে কোনও আইএসও ৮৮৮৯ -১ পড়ে থাকে (এবং এভাবে স্ট্রিংটিতে অবৈধ ইউটিএফ -8 রয়েছে) তবে আপনি এটিকে ISO_859-1 হিসাবে "স্ট্রিং.ফোর্স_এনকোডিং" ("ISO8859-1") দিয়ে পুনরায় ব্যাখ্যা করতে পারবেন এবং কেবলমাত্র কাজ করুন এটির সত্যিকারের এনকোডিংয়ের সাথে string
রুবেনলগুনা

3
সেই ডাবল এনকোড ট্রিকটি কেবল আমার বেকনকে বাঁচিয়েছে! আমি ভাবছি কেন এটি প্রয়োজন কেন?
জনফ

1
কোথায় আমি এই লাইন করা উচিত?
লেফসলার

5
আমি মনে করি ডাবল রূপান্তরটি কাজ করে কারণ এটি একটি এনকোডিং রূপান্তরকে বাধ্য করে (এবং এটির সাথে অবৈধ অক্ষরের জন্য চেক)। যদি উত্সের স্ট্রিংটি ইতিমধ্যে ইউটিএফ -8 এ এনকোড করা থাকে, তবে কেবল কলিংটি .encode('UTF-8')কোনও অপশন নয়, এবং কোনও চেক চালানো হয় না। এনকোডের জন্য রুবি কোর ডকুমেন্টেশন । যাইহোক, এটি ইউটিএফ -16 এ রূপান্তরিত করে প্রথমে অবৈধ বাইট সিকোয়েন্সগুলির জন্য সমস্ত চেক চালানো বাধ্য করে, এবং প্রতিস্থাপনগুলি প্রয়োজনীয় হিসাবে সম্পন্ন করা হয়।
জো হুন্ড

79

গৃহীত উত্তর বা অন্য উত্তর আমার পক্ষে কাজ করে না। আমি এই পোস্টটি খুঁজে পেয়েছি যা প্রস্তাবিত

string.encode!('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')

এটি আমার জন্য সমস্যাটি স্থির করেছে।


1
এটি আমার জন্য সমস্যাটি স্থির করে এবং আমি নন-অবহিত পদ্ধতি ব্যবহার করতে চাই (আমার এখন রুবি ২.০ আছে)।
লা-কোমাদ্রেজা

1
এই একটাই যে কাজ করে! আমি উপরের সমস্ত সমাধানের চেষ্টা করেছি, তাদের মধ্যে কেউই স্ট্রিংয়ের কাজ করে না যা "fdsfdsf dfsf sfds fs sdf <div> হ্যালো <p> fooo ??? {! @ # $% ^ & * () _ +} < / p> </div> \ xEF \ xBF \ xBD \ xef \ xbf \ x9c <div> \ xc2 \ x90 </div> \ xc2 \ x90 "
চিহং ইউ

1
দ্বিতীয় আর্গুমেন্ট 'বাইনারি' কীসের জন্য?
হেনলি চিউ

24

আমার বর্তমান সমাধানটি চালানো হচ্ছে:

my_string.unpack("C*").pack("U*")

এটি অন্ততপক্ষে ব্যতিক্রমগুলি থেকে মুক্তি পাবে যা আমার প্রধান সমস্যা ছিল


3
আমি এই পদ্ধতিটি সংমিশ্রণে ব্যবহার করছি valid_encoding?যা মনে হয় কখন কোনও ভুল হয় detect val.unpack('C*').pack('U*') if !val.valid_encoding?
অ্যারন জিব্রাল্টার

এই আমার জন্য কাজ করে। সাফল্যের সাথে আমার পিঠকে \xB0ডিগ্রী প্রতীকগুলিতে রূপান্তরিত করে । এমনকি valid_encoding?ফিরে সত্য কিন্তু যদি এটা না আমি এখনও চেক করুন এবং উপরে আমিরের উত্তর ব্যবহার আপত্তিকর অক্ষর আউট স্ট্রিপ: string.encode!('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')। আমিও force_encodingরুটটি চেষ্টা করেছিলাম কিন্তু তা ব্যর্থ হয়েছিল।
হামস্টার

এটা অসাধারণ. ধন্যবাদ।
d_ethier


4

আমি আপনাকে এইচটিএমএল পার্সার ব্যবহার করার পরামর্শ দিচ্ছি। দ্রুততমটি সন্ধান করুন।

পার্সিং এইচটিএমএল যতটা সহজ মনে হচ্ছে তত সহজ নয়।

ব্রাউজারগুলি ইউটিএফ -8 এইচটিএমএল নথিগুলিতে অবৈধ ইউটিএফ -8 সিকোয়েন্সগুলি বিশ্লেষণ করে কেবল " " চিহ্ন রেখে দেয়। সুতরাং একবার এইচটিএমএলে অবৈধ ইউটিএফ -8 সিকোয়েন্সটি পার্স হওয়ার পরে ফলাফলটি পাঠ্যটি একটি বৈধ স্ট্রিং।

এমনকি বৈশিষ্ট্যের মানগুলির ভিতরেও আপনাকে এমপিএল এর মতো এইচটিএমএল সত্তা ডিকোড করতে হয়

এখানে একটি দুর্দান্ত প্রশ্ন যা আপনি নিয়মিত অভিব্যক্তির সাহায্যে এইচটিএমএলকে নির্ভরযোগ্যভাবে পার্স করতে পারবেন না তার সমষ্টি: এক্সএইচটিএমএল স্ব-অন্তর্নিহিত ট্যাগগুলি বাদ দিয়ে রেজিএক্স ওপেন ট্যাগগুলির সাথে মেলে


2
আমি রেজিএক্সপাকে প্রায় 10 বার দ্রুত রাখার জন্য পছন্দ করব এবং আমি সত্যই এইচটিএমএলকে সঠিকভাবে পার্স করতে চাই না তবে কেবল লিঙ্কগুলি বের করতে চাই। আমার কেবল রুবিতে অবৈধ অংশগুলি প্রতিস্থাপন করতে সক্ষম হবে: ঠিক_ স্ট্রিং = খারাপ_ স্ট্রিং.ইনকোড ("ইউটিএফ -8", {: অবৈধ =>: প্রতিস্থাপন,: আনডিফ =>: প্রতিস্থাপন করুন) তবে এটি মনে হয় না কাজ :(
মার্ক সিগার

3

এটি কাজ করে বলে মনে হচ্ছে:

def sanitize_utf8(string)
  return nil if string.nil?
  return string if string.valid_encoding?
  string.chars.select { |c| c.valid_encoding? }.join
end

3
attachment = file.read

begin
   # Try it as UTF-8 directly
   cleaned = attachment.dup.force_encoding('UTF-8')
   unless cleaned.valid_encoding?
     # Some of it might be old Windows code page
     cleaned = attachment.encode( 'UTF-8', 'Windows-1252' )
   end
   attachment = cleaned
 rescue EncodingError
   # Force it to UTF-8, throwing out invalid bits
   attachment = attachment.force_encoding("ISO-8859-1").encode("utf-8", replace: nil)
 end

2

আমি স্ট্রিংয়ের মুখোমুখি হয়েছি, যার মধ্যে ইংরাজী, রাশিয়ান এবং কিছু অন্যান্য বর্ণমালার মিশ্রণ ছিল, যা ব্যতিক্রম ঘটায়। আমার কেবল রাশিয়ান এবং ইংরেজি প্রয়োজন এবং এটি বর্তমানে আমার পক্ষে কাজ করে:

ec1 = Encoding::Converter.new "UTF-8","Windows-1251",:invalid=>:replace,:undef=>:replace,:replace=>""
ec2 = Encoding::Converter.new "Windows-1251","UTF-8",:invalid=>:replace,:undef=>:replace,:replace=>""
t = ec2.convert ec1.convert t

1

নাকিলনের সমাধানটি কমপক্ষে ত্রুটিটি পেরিয়ে যাওয়ার ক্ষেত্রে, আমার ক্ষেত্রে, আমি মাইক্রোসফ্ট এক্সেল থেকে উদ্ভূত এই অদ্ভুত এফ-এড চরিত্রটি সিএসভিতে রূপান্তরিত করেছি যা রুবিতে নিবন্ধিত ছিল (এটি পান) সিরিলিক কে যা রুবি হ'ল একটি সাহসী কে। এটি ঠিক করার জন্য আমি 'আইসো -8859-1' ব্যবহার করেছি। CSV.parse(f, :encoding => "iso-8859-1"), যা আমার অদ্ভুত ডেকি সিরিলিক কে এর আরও অনেক বেশি পরিচালিত করে তোলে /\xCA/, যা আমি তারপরে মুছে ফেলতে পারতামstring.gsub!(/\xCA/, '')


আবার, আমি কেবল লক্ষ করতে চাই যে নাকিলনের (এবং অন্যান্য) ফিক্সটি ছিল সিরিলিক চরিত্রগুলির জন্য (হা হা) সিরিলিয়া থেকে উদ্ভূত, এই আউটপুটটি কোনও সিএসভির স্ট্যান্ডার্ড আউটপুট যা এক্সএলএস থেকে রূপান্তরিত হয়েছিল!
বোল্ডার_রবি

0

আপনি ব্যবহার করার আগে scan, অনুরোধ করা পৃষ্ঠার Content-Typeশিরোনামটি নিশ্চিত হয়ে নিন text/html, যেহেতু ইউটিএফ -8 এ এনকোডেড নয় এমন চিত্রগুলির মতো লিঙ্ক থাকতে পারে। আপনি যদি hrefকোনও <link>উপাদানের মতো কোনও কিছু চয়ন করেন তবে পৃষ্ঠাটি অ-এইচটিএমএলও হতে পারে । কীভাবে এটি চেক করবেন তা আপনি কোন HTTP লাইব্রেরি ব্যবহার করছেন তার পরিবর্তিত হয়। তারপরে, নিশ্চিত হয়ে নিন যে ফলাফলটি কেবলমাত্র এএসসিই String#ascii_only?(ইউটিএফ -8 নয় কারণ HTML কেবলমাত্র এসকিআই ব্যবহার করার কথা বলেছে, সত্তা অন্যথায় ব্যবহার করা যেতে পারে)। যদি এই দুটি পরীক্ষাই পাস করে তবে এটি ব্যবহার করা নিরাপদ scan


ধন্যবাদ, তবে এটি আমার সমস্যা নয় :) আমি যেভাবেই হোক ইউআরএলটির হোস্ট অংশটি বের করেছি এবং কেবল প্রথম পৃষ্ঠায় হিট করেছি। আমার সমস্যাটি হ'ল আমার ইনপুটটি আপাতদৃষ্টিতে ইউটিএফ -8 নয় এবং 1.9 এনকোডিং ফু ফুটে উঠেছে
মার্ক সিগার

@ মার্ক সিগার: "আমার ইনপুট" বলতে কী বোঝ? স্টিডিন, ইউআরএল, বা পৃষ্ঠার মূল অংশ?
অ্যাড্রিয়ান

এইচটিএমএল ইউটিএফ -8 এ এনকোড করা যেতে পারে: en.wikedia.org/wiki/Character_encodings_in_HTML
এডুয়ার্ডো

আমার ইনপুট = পৃষ্ঠার বডি @ এডুয়ার্ডো: আমি জানি। আমার সমস্যাটি হ'ল নেট / এইচটিপি থেকে আসা ডেটা সময়ে সময়ে একটি খারাপ এনকোডিং বলে মনে হচ্ছে
মার্ক সিগার

ওয়েবপৃষ্ঠাগুলির বাস্তবের জন্য খারাপ এনকোডিং থাকা অস্বাভাবিক নয়। প্রতিক্রিয়া শিরোনাম বলতে পারে এটি একটি এনকোডিং তবে পরে অন্য একটি এনকোডিং পরিবেশন করছে।
sunkencity

-1

আপনি যদি ডেটা সম্পর্কে "যত্ন" না করেন তবে আপনি ঠিক যেমন কিছু করতে পারেন:

search_params = params[:search].valid_encoding? ? params[:search].gsub(/\W+/, '') : "nothing"

আমি শুধু valid_encoding?এটি পাস করতে ব্যবহৃত । খনি একটি অনুসন্ধান ক্ষেত্র, এবং তাই আমি বার বার একই অদ্ভুততা খুঁজে পেয়েছিলাম তাই আমি এরকম কিছু ব্যবহার করেছি: কেবল সিস্টেমটি না ভাঙতে। যেহেতু আমি এই তথ্যটি প্রেরণ করার আগে ব্যবহারকারীর অভিজ্ঞতাটিকে অটোওয়ালিডেট করতে নিয়ন্ত্রণ করি না (যেমন "ডামি আপ!" বলতে অটো ফিডব্যাকের মতো) আমি কেবল এটি নিয়ে যেতে পারি, এটিকে ছড়িয়ে দিতে পারি এবং ফাঁকা ফলাফল দিতে পারি।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.