title: Is there any way to make browser page avoiding redirects in Pyqt5?
body: <p>I am working with pyqt5. I want user to click the browser embeded on my pyqt5 application to get the XPATH of the element which he/she is clicking on it.</p>
  
  <p>I got the solution how to implement the above idea by someone but the page on the browser gets redirected to another page of the website. </p>
  
  <p>What if I want the user to click the element, but not allowing him to go further by clicking on the buttons and getting away from the original page. In short, I just want to stick on that same page without redirecting to the another one so as to get the XPATH's of the same page only. </p>
  
  <p>Here's the working code as follows suggested by @eyllanesc  :</p>
  
  <p><strong>My file</strong></p>
  
  <pre><code>├── main.py
  └── xpath_from_element.js
  </code></pre>
  
  <p><strong>Main.py</strong></p>
  
  <pre><code>import os
  
  from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets, QtWebChannel
  
  from jinja2 import Template
  
  CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
  
  
  class Element(QtCore.QObject):
      def __init__(self, name, parent=None):
          super(Element, self).__init__(parent)
          self._name = name
  
      @property
      def name(self):
          return self._name
  
      def script(self):
          return ""
  
  
  class WebEnginePage(QtWebEngineWidgets.QWebEnginePage):
      def __init__(self, parent=None):
          super(WebEnginePage, self).__init__(parent)
          self.loadFinished.connect(self.onLoadFinished)
          self._objects = []
          self._scripts = []
  
      def add_object(self, obj):
          self._objects.append(obj)
  
      @QtCore.pyqtSlot(bool)
      def onLoadFinished(self, ok):
          print("Finished loading: ", ok)
          if ok:
              self.load_qwebchannel()
              self.add_objects()
  
      def load_qwebchannel(self):
          file = QtCore.QFile(":/qtwebchannel/qwebchannel.js")
          if file.open(QtCore.QIODevice.ReadOnly):
              content = file.readAll()
              file.close()
              self.runJavaScript(content.data().decode())
          if self.webChannel() is None:
              channel = QtWebChannel.QWebChannel(self)
              self.setWebChannel(channel)
  
      def add_objects(self):
          if self.webChannel() is not None:
              objects = {obj.name: obj for obj in self._objects}
              self.webChannel().registerObjects(objects)
              _script = """
              {% for obj in objects %}
              var {{obj}};
              {% endfor %}
              new QWebChannel(qt.webChannelTransport, function (channel) {
              {% for obj in objects %}
                  {{obj}} = channel.objects.{{obj}};
              {% endfor %}
              }); 
              """
              self.runJavaScript(Template(_script).render(objects=objects.keys()))
              for obj in self._objects:
                  if isinstance(obj, Element):
                      self.runJavaScript(obj.script())
  
  
  class Helper(Element):
      xpathClicked = QtCore.pyqtSignal(str)
  
      def script(self):
          js = ""
          file = QtCore.QFile(os.path.join(CURRENT_DIR, "xpath_from_element.js"))
          if file.open(QtCore.QIODevice.ReadOnly):
              content = file.readAll()
              file.close()
              js = content.data().decode()
  
          js += """
          document.addEventListener('click', function(e) {
              e = e || window.event;
              var target = e.target || e.srcElement;
              var xpath = Elements.DOMPath.xPath(target, false); 
              {{name}}.receive_xpath(xpath);
          }, false);"""
          return Template(js).render(name=self.name)
  
      @QtCore.pyqtSlot(str)
      def receive_xpath(self, xpath):
          self.xpathClicked.emit(xpath)
  
  
  if __name__ == "__main__":
      import sys
  
      app = QtWidgets.QApplication(sys.argv)
  
      xpath_helper = Helper("xpath_helper")
      xpath_helper.xpathClicked.connect(lambda xpath: print("clicked", xpath))
      view = QtWebEngineWidgets.QWebEngineView()
      page = WebEnginePage()
      page.add_object(xpath_helper)
      view.setPage(page)
      view.load(QtCore.QUrl("https://www.qt.io"))
      view.show()
      sys.exit(app.exec_())
  </code></pre>
  
  <p><strong>xpath_from_element.js</strong></p>
  
  <pre><code>
  // Copyright 2018 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  Elements = {};
  Elements.DOMPath = {};
  
  /**
   * @param {!Node} node
   * @param {boolean=} optimized
   * @return {string}
   */
  Elements.DOMPath.xPath = function (node, optimized) {
      if (node.nodeType === Node.DOCUMENT_NODE) {
          return '/';
      }
  
      const steps = [];
      let contextNode = node;
      while (contextNode) {
          const step = Elements.DOMPath._xPathValue(contextNode, optimized);
          if (!step) {
              break;
          }  // Error - bail out early.
          steps.push(step);
          if (step.optimized) {
              break;
          }
          contextNode = contextNode.parentNode;
      }
  
      steps.reverse();
      return (steps.length &amp;&amp; steps[0].optimized ? '' : '/') + steps.join('/');
  };
  
  /**
   * @param {!Node} node
   * @param {boolean=} optimized
   * @return {?Elements.DOMPath.Step}
   */
  Elements.DOMPath._xPathValue = function (node, optimized) {
      let ownValue;
      const ownIndex = Elements.DOMPath._xPathIndex(node);
      if (ownIndex === -1) {
          return null;
      }  // Error.
  
      switch (node.nodeType) {
          case Node.ELEMENT_NODE:
              if (optimized &amp;&amp; node.getAttribute('id')) {
                  return new Elements.DOMPath.Step('//*[@id="' + node.getAttribute('id') + '"]', true);
              }
              ownValue = node.localName;
              break;
          case Node.ATTRIBUTE_NODE:
              ownValue = '@' + node.nodeName;
              break;
          case Node.TEXT_NODE:
          case Node.CDATA_SECTION_NODE:
              ownValue = 'text()';
              break;
          case Node.PROCESSING_INSTRUCTION_NODE:
              ownValue = 'processing-instruction()';
              break;
          case Node.COMMENT_NODE:
              ownValue = 'comment()';
              break;
          case Node.DOCUMENT_NODE:
              ownValue = '';
              break;
          default:
              ownValue = '';
              break;
      }
  
      if (ownIndex &gt; 0) {
          ownValue += '[' + ownIndex + ']';
      }
  
      return new Elements.DOMPath.Step(ownValue, node.nodeType === Node.DOCUMENT_NODE);
  };
  
  /**
   * @param {!Node} node
   * @return {number}
   */
  Elements.DOMPath._xPathIndex = function (node) {
      // Returns -1 in case of error, 0 if no siblings matching the same expression,
      // &lt;XPath index among the same expression-matching sibling nodes&gt; otherwise.
      function areNodesSimilar(left, right) {
          if (left === right) {
              return true;
          }
  
          if (left.nodeType === Node.ELEMENT_NODE &amp;&amp; right.nodeType === Node.ELEMENT_NODE) {
              return left.localName === right.localName;
          }
  
          if (left.nodeType === right.nodeType) {
              return true;
          }
  
          // XPath treats CDATA as text nodes.
          const leftType = left.nodeType === Node.CDATA_SECTION_NODE ? Node.TEXT_NODE : left.nodeType;
          const rightType = right.nodeType === Node.CDATA_SECTION_NODE ? Node.TEXT_NODE : right.nodeType;
          return leftType === rightType;
      }
  
      const siblings = node.parentNode ? node.parentNode.children : null;
      if (!siblings) {
          return 0;
      }  // Root node - no siblings.
      let hasSameNamedElements;
      for (let i = 0; i &lt; siblings.length; ++i) {
          if (areNodesSimilar(node, siblings[i]) &amp;&amp; siblings[i] !== node) {
              hasSameNamedElements = true;
              break;
          }
      }
      if (!hasSameNamedElements) {
          return 0;
      }
      let ownIndex = 1;  // XPath indices start with 1.
      for (let i = 0; i &lt; siblings.length; ++i) {
          if (areNodesSimilar(node, siblings[i])) {
              if (siblings[i] === node) {
                  return ownIndex;
              }
              ++ownIndex;
          }
      }
      return -1;  // An error occurred: |node| not found in parent's children.
  };
  
  /**
   * @unrestricted
   */
  Elements.DOMPath.Step = class {
      /**
       * @param {string} value
       * @param {boolean} optimized
       */
      constructor(value, optimized) {
          this.value = value;
          this.optimized = optimized || false;
      }
  
      /**
       * @override
       * @return {string}
       */
      toString() {
          return this.value;
      }
  };
  </code></pre>
  
  <p>Original answered at <a href="https://stackoverflow.com/questions/60492526/is-there-any-way-of-getting-xpath-of-the-page-in-pyqt5-in-browser">Is there any way of getting XPATH of the page in Pyqt5 in browser?</a> 
  Any help would be appreciated...</p>