Gem 特复杂的页面怎么解析

yakczh · 2015年08月29日 · 最后由 roclv 回复于 2015年08月31日 · 2251 次阅读
require 'rubygems' 
require 'nokogiri'
require 'open-uri'  

 uri = "http://www.hao123.com/"  

doc = Nokogiri::HTML(open(uri),nil.'utf8') 
 #html=open('hao123.html').read 
 #doc= Nokogiri::HTML(html,nil,'utf8');


 sites=doc.at("#box-coolsite")
 puts sites

要取得 主体部分的站点列表 ,但是取不出来,用 hpricot 也是一样

可以看出 #box-coolsite<code id="__cnt_0_19" ... 内,并被注释了,你可以先获取<code 内的 inner_html, 然后对里面的数据进行处理。 hao123 源码

xpath 能获取注释吗?

使用 inner_html 方法来获取code tag 内容后处理。

doc.at("#__cnt_0_19").inner_html
# -*- coding:utf-8 -*-
require 'hpricot'
data=<<D
<span>环球新军事</span>
D
#data.force_encoding("UTF-8")
page=Hpricot(data,'utf8')
(page/"span").each do |x|
 print   9.chr,x.inner_text
 puts
end

这个地方过不去了 `gsub': invalid byte sequence in GBK (ArgumentError) 貌似是 inner_text 的处理是递归找到节点的 inner_text 然后调用 uxs 对文本中的 html 字符实体做替换,有些中文字节的值刚好跟字符实体 NamedCharacters 中定义的值相同,就乱码了,最后输出 “” 环球新军仜 x8B" “ print 报错了 inner_text 的实现在 \Ruby2.1.0\lib\ruby\gems\2.1.0\gems\hpricot-0.8.6\lib\hpricot\traverse.rb 162 行

def inner_text
  if respond_to?(:children) and children
      children.map { |x|
                           # x=   "\xE7\x8E\xAF\xE7\x90\x83\xE6\x96\xB0\xE5\x86\x9B\xE4\xBA\x8B"
     x.inner_text
    }.join
  else
    ""
  end
end

\Ruby2.1.0\lib\ruby\gems\2.1.0\gems\hpricot-0.8.6\lib\hpricot\tag.rb 中定义了
Text 节点的 to_s

class Text
  def initialize content; self.content = content end
  def pathname; "text()" end
  def to_s
    Hpricot.uxs(content)
  end

uxs 的实现在 \Ruby2.1.0\lib\ruby\gems\2.1.0\gems\hpricot-0.8.6\lib\hpricot\builder.rb

module Hpricot
  # XML unescape
  def self.uxs(str)
    str.to_s.gsub(/\&(\w+);/) { [NamedCharacters[$1] || 63].pack("U*") }. # 63 = ?? (query char).
     gsub(/\&\#(\d+);/) { [$1.to_i].pack("U*") }.
     gsub(/\&\#x([0-9a-fA-F]+);/) { [$1.to_i(16)].pack("U*") }
  end

如果是中英文混排
“ 环球 &nbsp;&#163; 新军事 “ gsub 替换是按字节替换吗? 有没有办法只替换英文部分?

取不出来?也许是一些要用到 js 解释器来触发?

配合 SelectorGadget 使用

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册