在抓取表单时,我更喜欢按标签查找字段,因为我正在使用的页面的大多数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 = "..."
这是一个黑客,但它现在有效。我可以使用更优雅的解决方案吗?
答案 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
这有点干净但仍然一团糟。我需要有一个真正的理由去做,我会很恼火地在我继承的代码中找到它。