PhantomJS; nhấp vào một phần tử


81

Làm cách nào để nhấp vào một phần tử trong PhantomJS?

page.evaluate(function() {
    document.getElementById('idButtonSpan').click();  
});

Điều này khiến tôi gặp lỗi "undefined không phải là một hàm ..."

Nếu tôi thay thế

 return document.getElementById('idButtonSpan');

và sau đó in nó,

sau đó nó in ra [object object], vì vậy phần tử tồn tại.

Phần tử hoạt động như một nút, nhưng nó thực sự chỉ là một phần tử span, không phải là một đầu vào gửi.

Tôi đã có thể nhấp vào nút này để làm việc với Casper, nhưng Casper có những hạn chế khác nên tôi quay lại PhantomJS.


28
Đã đến lúc chấp nhận một câu trả lời.

Có 3 câu trả lời sử dụng chức năng "DispatchEvent", 2 câu trả lời sử dụng "sendEvent", một câu trả lời thực tế vô dụng và một câu trả lời phải là bình luận.
redbeam_

Đừng quên dấu # ...
GracefulCode

Tại sao vẫn chưa có ai chỉ ra rằng click()nó hoàn toàn không tồn tại trong DOM API, có thể bạn đã thấy nó trong jQuery hoặc một số lib như vậy?
YemSalat,

4 năm sau: Câu trả lời được chấp nhận! Tôi đã rời khỏi PhantomJS nên không thể xác minh câu trả lời. Nhưng tôi chấp nhận rằng 58 phiếu ủng hộ là chính xác :) @torazaburo
user984003

Câu trả lời:


68

.click()không phải là tiêu chuẩn. Bạn cần tạo một sự kiện và gửi nó đi:

function click(el){
    var ev = document.createEvent("MouseEvent");
    ev.initMouseEvent(
        "click",
        true /* bubble */, true /* cancelable */,
        window, null,
        0, 0, 0, 0, /* coordinates */
        false, false, false, false, /* modifier keys */
        0 /*left*/, null
    );
    el.dispatchEvent(ev);
}

9
Kết elhợp với jQuery cung cấp cho bạn định nghĩa nhấp chuột này. Nó sẽ hoạt động trong trình duyệt của bạn và trong Phantom. $(el).click()
Bluu

3
omg nước mắt của niềm vui, sau gần 12 giờ đấu tranh liên tục với điều này! ngửi ngửi!
dùng1323136

1
Hoạt động tốt đối với tôi, nhưng người ta phải nhớ không thoát PhantomJS quá sớm, trước khi quá trình xử lý kết thúc. Tôi cần một tập lệnh ngắn để chỉ cần nhấp vào một nút và thoát. Điều này sẽ không hoạt động đối với tôi cho đến khi tôi gọi phantom.exit () từ bên trong page.onLoadFinishing = function () {...};
gregko

document.querySelector (element) .click () phù hợp với tôi.
GracefulCode

Để làm việc với các điều khiển tùy chỉnh, tôi phải đưa ra giải pháp phức tạp hơn với 3 sự kiện: function triggerMouseEvent (elm, eventType) {var ev = document.createEvent ("MouseEvent"); ev.initMouseEvent (eventType, true / * bubble /, true / hủy /, cửa sổ, null, 0, 0, 0, 0, / tọa độ / false, false, false, false, / các phím bổ trợ * / 0 / * left * /, vô giá trị ); elm.dispatchEvent (ev); } function click (elm) {triggerMouseEvent (elm, 'mousedown'); triggerMouseEvent (elm, 'mouseup'); triggerMouseEvent (elm, 'click'); }
a-bobkov

34

Ngoài ra đối với phản hồi của @ torazaburo, bạn có thể bị HTMLElement.prototype.clickđơ khi chạy trong PhantomJS. Ví dụ: chúng tôi sử dụng PhantomJS + QUnit để chạy các bài kiểm tra của mình và trong chúng qunit-config.jstôi có một cái gì đó như sau:

if (window._phantom) {
  // Patch since PhantomJS does not implement click() on HTMLElement. In some 
  // cases we need to execute the native click on an element. However, jQuery's 
  // $.fn.click() does not dispatch to the native function on <a> elements, so we
  // can't use it in our implementations: $el[0].click() to correctly dispatch.
  if (!HTMLElement.prototype.click) {
    HTMLElement.prototype.click = function() {
      var ev = document.createEvent('MouseEvent');
      ev.initMouseEvent(
          'click',
          /*bubble*/true, /*cancelable*/true,
          window, null,
          0, 0, 0, 0, /*coordinates*/
          false, false, false, false, /*modifier keys*/
          0/*button=left*/, null
      );
      this.dispatchEvent(ev);
    };
  }
}

1
Lưu ý rằng tôi đang chạy Karma 0.12.17 với PhantomJs 1.9.7-14. Không có window._phantomđối tượng vì vậy tôi chỉ cần loại bỏ điều kiện đó và nó hoạt động như mong đợi.
BradGreens

Tôi tự hỏi liệu hàm có nên chấp nhận các tham số để đặt các tọa độ khác nhau cho MouseEvent hay không
ffflabs 02/02

16

Nó không đẹp, nhưng tôi đã sử dụng cái này để cho phép tôi sử dụng jQuery cho lựa chọn:

var rect = page.evaluate(function() {
    return $('a.whatever')[0].getBoundingClientRect();
});
page.sendEvent('click', rect.left + rect.width / 2, rect.top + rect.height / 2);

nhưng bạn luôn có thể thay thế $(s)[0] bằng document.querySelector(s)nếu không sử dụng jQuery.

(Nó phụ thuộc vào yếu tố có trong tâm trí chế độ xem, tức là viewportSize.height của bạn đủ lớn).


2
Đã thử tất cả các phương pháp có thể và đây là tùy chọn duy nhất phù hợp với tôi khi cố gắng nhấp vào tr.
Kai

Làm việc trên phantomjs 1.9.0 và với phần tử <a>
redbeam_

1
giải pháp tốt nhất imo,+1
Flash Thunder

10

Hy vọng phương pháp sau đây sẽ hữu ích. Nó hoạt động với tôi trong phiên bản 1.9

page.evaluate(function(){
    var a = document.getElementById("spr-sign-in-btn-standard");
    var e = document.createEvent('MouseEvents');
    e.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
    a.dispatchEvent(e);
    waitforload = true;
});

Điều này đã làm việc cho tôi. Hy vọng điều này cũng sẽ hữu ích cho những người khác


@Jobins john whats waitforload = true?
Qadir Hussain

1
@QadirHussain Nó thực sự đang đợi trang tải hoàn toàn. Nó gần giống như thiết lập một thời gian cụ thể để tải trang.
Jobins John

6

Với 1.9.2điều này đã làm việc cho tôi, các trình xử lý nhấp chuột đã được kích hoạt:

var a = page.evaluate(function() {
    return document.querySelector('a.open');
});

page.sendEvent('click', a.offsetLeft, a.offsetTop);

Nó không có trên tất cả các yếu tố. Ví dụ <a> không có nó. Trên các nút, nó ở đó.
unludo

6

sử dụng JavaScript đơn giản với evaluate, tương tự như sau:

page.evaluate(function() {
    document.getElementById('yourId').click();
});

1
Trên thực tế nó bây giờ là giải pháp đúng bây giờ với PhantomJS 2.x
BlaM

3

Tôi chưa bao giờ có thể nhấp trực tiếp vào phần tử. Thay vào đó, tôi nhìn vào html để tìm hàm nào được gọi với onclick và sau đó gọi hàm đó.


làm thế nào bạn có thể tìm thấy hàm và cách bạn gọi nó nếu nó đã được đính kèm thông qua addEventListener?
Suo6613,

2

Document.querySelector (phần tử) .click () hoạt động khi sử dụng Phantomjs 2.0

click: function (selector, options, callback) {
    var self = this;
    var deferred = Q.defer();
    options = options || {timeout:1000}; 
    setTimeout(function () { 
        self.page.evaluate(function(targetSelector) {
            $(document).ready(function() {
                document.querySelector(targetSelector).click();
            }) ;
        }, function () {
                deferred.resolve();
        }, selector);
    }, options.timeout);
    return deferred.promise.nodeify(callback);
},

2

Cũng có thể nhấp đúp với PhantomJS.

Được đề xuất

Điều này được điều chỉnh từ câu trả lời của stovroz và kích hoạt một bản địa dblclickbao gồm mousedown, mouseupclickcác sự kiện (hai trong số mỗi sự kiện).

var rect = page.evaluate(function(selector){
    return document.querySelector(selector).getBoundingClientRect();
}, selector);
page.sendEvent('doubleclick', rect.left + rect.width / 2, rect.top + rect.height / 2);

Những cách khác

Hai cách sau đây chỉ kích hoạt dblclicksự kiện, nhưng không kích hoạt các sự kiện khác trước nó.

Phỏng theo câu trả lời này của torazaburo :

page.evaluate(function(selector){
    var el = document.querySelector(sel);
    var ev = document.createEvent("MouseEvent");
    ev.initMouseEvent(
        'dblclick',
        true /* bubble */, true /* cancelable */,
        window, null,
        0, 0, 0, 0, /* coordinates */
        false, false, false, false, /* modifier keys */
        0 /*left*/, null
    );
    el.dispatchEvent(ev);
}, selector);

Phỏng theo câu trả lời này của Jobins John :

page.evaluate(function(selector){
    var el = document.querySelector(sel);
    var e = document.createEvent('MouseEvents');
    e.initMouseEvent('dblclick', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
    el.dispatchEvent(e);
}, selector);

Tập lệnh thử nghiệm đầy đủ


2

Cách dễ nhất là sử dụng jQuery.

page.evaluate(function() {
  page.includeJs("your_jquery_file.js", function() {
    page.evaluate(function() {
      $('button[data-control-name="see_more"]').click();
    });
  });
});

0

Đối với những người sử dụng JQuery, giao diện người dùng JQuery đã tạo một tiện ích để mô phỏng những điều này: jquery-simulate . Tôi sử dụng cái này trong PhantomJS và Chrome

$ele..simulate( "click" );
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.