正则匹配编码兼容错误排查:UTF-8正则与ASCII-8BIT字符串匹配失败
解决Ruby中Encoding::CompatibilityError的编码不匹配问题
这问题我之前写网页爬虫时也踩过一模一样的坑!本质是字符串编码和正则编码不兼容——虽然你确认页面是UTF-8,但HTTP.get返回的响应体默认是以ASCII-8BIT(二进制)格式存储的,而你的正则表达式是UTF-8编码的,两者一匹配就触发了兼容性错误。下面给你分步解决:
核心思路:统一编码 + 修正正则匹配逻辑
首先要把响应体的编码明确为页面实际编码,再转成UTF-8确保和正则编码一致;同时修正正则表达式,因为你之前用的是HTML转义实体<,但网页源码里的标签是原始的<,这也会导致部分匹配失效。
修正后的完整代码
urls.each do |url| response = HTTP.get(url) if response.status.success? # 1. 处理编码:优先从响应头获取页面charset,无则默认UTF-8 content_type = response.headers['Content-Type'] || '' charset = content_type.match(/charset=([^;]+)/) ? $1.strip : 'UTF-8' # 强制指定编码并转成UTF-8,替换无效/未定义字符避免报错 source_code = response.body.force_encoding(charset).encode( 'UTF-8', invalid: :replace, undef: :replace, replace: '' ) # 2. 修正正则:匹配原始HTML标签而非转义实体 # 移除HTML注释(支持跨行) source_code = source_code.gsub(/<!--(.*?)-->/m, '') # 移除所有script标签及其内容(兼容大小写和任意属性) source_code = source_code.gsub(/<script\b[^>]*>(.*?)<\/script>/mi, '') if source_code.match(/out of stock/i) # 标记URL做后续处理 puts "#{url} 检测到缺货提示!" end end end
关键细节说明
- 编码处理:
force_encoding只是告诉Ruby二进制字符串的实际编码,encode才是真正把它转成UTF-8;invalid: :replace和undef: :replace能避免页面存在无效字符时抛出异常,让程序更健壮。 - 正则优化:用
<替代<才能匹配源码里的真实标签,\b确保匹配完整的script标签开头(避免误匹配noscript这类相似标签),mi修饰符让匹配忽略大小写且支持跨行内容。 - 兼容性提升:从响应头提取charset比硬编码UTF-8更靠谱,能自动适配GBK、Shift_JIS等其他编码的页面。
内容的提问来源于stack exchange,提问作者Jordan Lagan
相关产品推荐
相关产品推荐

