机械化:按标签文本匹配字段

时间:2014-02-05 21:16:18

标签: ruby label mechanize

在抓取表单时,我更喜欢按标签查找字段,因为我正在使用的页面的大多数ID和名称都是自动生成的,我不能相信它们不会更改,而且标签很多比名字更具描述性。

而不是一直在我的脚本中执行此操作:

Mechanize::Page.elements_with 'label'
#...
some_form.field_with(
  some_form.page.label_with(:text => "Address").node['for']
).value = "..."

some_form.field_with(
  some_form.page.label_with(:text => "Zipcode").node['for']
).value = "..."

我已经开始在我的脚本顶部放置一个monkeypatch:

class Mechanize::Form::Field
  def label_text
    # hack to get the document root
    root = node.ancestors.last
    # look up the label for this field
    label = root.at("label[for=#{dom_id.inspect}]") if dom_id
    label && label.text
  end
 end

所以我可以这样做:

some_form.field_with( :label_text => "Address" ).value = "..."
some_form.field_with( :label_text => "Zipcode" ).value = "..."

这是一个黑客,但它现在有效。我可以使用更优雅的解决方案吗?

2 个答案:

答案 0 :(得分:1)

我找到了一个更好的解决方案,不涉及猴子修补。由于使用{element}_with匹配了===条件,因此我可以将lambda传递给# convenince methods to define matcher lambdas def has_title expected lambda { |node| expected === node['title'] end def has_label expected lambda do |node| # hack to get the document root root = node.ancestors.last dom_id = node['id'] # look up the label for this field label = root.at("label[for=#{dom_id.inspect}]") if dom_id # check if it matches expected === (label && label.text) end end some_form.field_with( :node => has_label("Address") ).value = "..." some_form.field_with( :node => has_label("Zipcode") ).value = "..." some_form.field_with( :node => has_title("Description") ).value = "..." ...

{{1}}

答案 1 :(得分:0)

你可以这样做:

def get_key page, str
  id = page.at("label[text()*='#{str}']")[:for]
  key = page.at("##{id}")[:name]
end

然后

form[get_key(page, 'Address')] = value

这有点干净但仍然一团糟。我需要有一个真正的理由去做,我会很恼火地在我继承的代码中找到它。