ruby - 루비 1.9:UTF-8에서 유효하지 않은 바이트 시퀀스




encoding (10)

Ruby (1.9)에 많은 무작위 사이트에서 많은 HTML을 사용하는 크롤러를 작성하고 있습니다.
링크를 추출 할 때 nokogiri / hpricot (주요 속도 향상) 대신 .scan(/href="(.*?)"/i) 사용하기로 결정했습니다. 문제는 이제 " invalid byte sequence in UTF-8 "오류가 많이 발생한다는 것입니다.
내가 이해 한 바로는 net/http 라이브러리에는 인코딩 옵션이 없으며 들어오는 내용은 기본적으로 제대로 태그되지 않았습니다.
들어오는 데이터로 실제로 작업하는 가장 좋은 방법은 무엇입니까? 나는 .encode 를 replace와 invalid 옵션 세트로 시도했지만, 지금까지는 성공하지 못했다 ...


Answers

받아 들여진 대답이나 다른 대답이 나를 위해 일한다. 이 게시물 을 찾았 습니다.

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

이 문제가 해결되었습니다.


scan 을 사용하기 전에 요청 된 페이지의 Content-Type 헤더가 text/html 인지 확인하십시오. UTF-8로 인코딩되지 않은 이미지와 같은 링크가있을 수 있기 때문입니다. 이 페이지는 <link> 엘리먼트와 같은 것으로 href 를 포착했다면 non-html이 될 수도 있습니다. 이를 확인하는 방법은 사용중인 HTTP 라이브러리에 따라 다릅니다. 그런 다음 결과가 String#ascii_only? ascii인지 확인하십시오 String#ascii_only? (HTML은 ascii만을 사용하기 때문에 UTF-8이 아니라 엔티티가 다르게 사용될 수 있습니다). 두 검사가 모두 통과하면 scan 를 사용하는 것이 안전합니다.


이 시도:

def to_utf8(str)
  str = str.force_encoding('UTF-8')
  return str if str.valid_encoding?
  str.encode("UTF-8", 'binary', invalid: :replace, undef: :replace, replace: '')
end

내 현재 솔루션을 실행하는 것입니다 :

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

적어도 내 주요한 문제인 예외를 제거 할 것입니다.


데이터에 대해 "신경 쓰지 않는"경우 다음과 같이 할 수 있습니다.

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

방금 valid_encoding? 사용 valid_encoding? 그것을 전달하십시오. 내 것은 검색 필드이므로, 나는 같은 이상한 것을 반복해서 찾아 내고 있었기 때문에 나는 시스템을 깨뜨리지 않기 위해 다음과 같은 것을 사용했다. 나는이 정보를 보내기 전에 자동 응답으로 사용자 환경을 제어하지 않으므로 (자동 피드백과 같이 "더미 업!"이라고 말함) 나는 그것을 받아 들여 빈 결과를 반환 할 수 있습니다.


이것은 작동하는 것 같습니다 :

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

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

Ruby 1.9.3에서는 String.encode를 사용하여 잘못된 UTF-8 시퀀스를 "무시"할 수 있습니다. 다음은 1.8 ( iconv ) 및 1.9 ( String#encode )에서 모두 작동하는 스 니펫입니다.

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

또는 정말로 귀찮은 입력이있는 경우 UTF-8에서 UTF-16으로 그리고 UTF-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

나는 영어, 러시아어 및 일부 다른 알파벳의 혼합이있는 문자열을 만났습니다. 예외가 발생했습니다. 러시아어와 영어 만 필요하며 현재이 기능은 다음과 같습니다.

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

spawn 명령을 잊지 말고 지정된 명령을 실행하는 백그라운드 프로세스를 작성하십시오. Process 클래스와 반환 된 pid 사용하여 완료를 기다릴 수도 있습니다.

pid = spawn("tar xf ruby-2.0.0-p195.tar.bz2")
Process.wait pid

pid = spawn(RbConfig.ruby, "-eputs'Hello, world!'")
Process.wait pid

의사는 다음과 같이 말합니다.이 방법은 #system 과 비슷하지만 명령이 완료 될 때까지 기다리지 않습니다.





ruby encoding utf-8