Puppeteer में टेक्स्ट वाले एलिमेंट पर कैसे क्लिक करें


86

क्या पाठ के साथ तत्व पर क्लिक करने के लिए कोई विधि (एपीआई में नहीं मिली) या समाधान है?

उदाहरण के लिए मेरे पास html है:

<div class="elements">
    <button>Button text</button>
    <a href=#>Href text</a>
    <div>Div text</div>
</div>

और मैं उस तत्व पर क्लिक करना चाहता हूं जिसमें पाठ लपेटा गया है (अंदर बटन पर क्लिक करें।), जैसे:

Page.click('Button text', '.elements')

2
यहाँ उत्तर साझा किया गया: stackoverflow.com/a/47829000/6161265
Md। अबू ताहिर

क्या आपको उत्तर मिला?
शुभम बत्रा

यदि यह मदद करता है, तो जिस पेज पर मैं एक क्लिक करना चाहता था, उसमें jQuery लोड है, इसलिए मैं jQuery कोड को निष्पादित करने के लिए मूल्यांकन पद्धति का उपयोग और उपयोग करने में सक्षम था।
ब्रैंडिटो

जवाबों:


78

वर्तमान शीर्ष जवाब tokland से केवल पाठ नोड्स पर और अन्य तत्वों के अंदर के साथ नोड्स पर नहीं काम करता है।

संक्षिप्त जवाब

यह एक्सपीथ एक्सप्रेशन एक बटन को क्वेरी करेगा जिसमें "बटन टेक्स्ट" लिखा है:

const [button] = await page.$x("//button[contains(., 'Button text')]");
if (button) {
    await button.click();
}

<div class="elements">आसपास के बटनों का सम्मान करने के लिए, निम्नलिखित कोड का उपयोग करें:

const [button] = await page.$x("//div[@class='elements']/button[contains(., 'Button text')]");

व्याख्या

यह समझाने के लिए कि text()कुछ मामलों में टेक्स्ट नोड ( ) का उपयोग गलत क्यों है, आइए एक उदाहरण देखें:

<div>
    <button>Start End</button>
    <button>Start <em>Middle</em> End</button>
</div>

उपयोग करते समय सबसे पहले, परिणाम देखें contains(text(), 'Text'):

  • //button[contains(text(), 'Start')]दोनों दो नोड्स लौटा देंगे (उम्मीद के मुताबिक)
  • //button[contains(text(), 'End')]केवल वापस आ जाएगी एक नोड्स (प्रथम) के रूप में text()रिटर्न एक दो ग्रंथों (साथ सूची Startऔर End), लेकिन containsकेवल पहले की जाँच करेगा
  • //button[contains(text(), 'Middle')]कोई परिणाम नहीं देगा क्योंकि text()इसमें बाल नोड्स का पाठ शामिल नहीं है

यहाँ XPath अभिव्यक्तियाँ हैं contains(., 'Text'), जो अपने बच्चे के नोड्स सहित तत्व पर ही काम करता है:

  • //button[contains(., 'Start')]दोनों दो बटन वापस करेंगे
  • //button[contains(., 'End')]फिर से दोनों दो बटन वापस करेंगे
  • //button[contains(., 'Middle')]एक (अंतिम बटन) वापस आएगा

तो ज्यादातर मामलों में, यह एक XPath अभिव्यक्ति के .बजाय उपयोग करने के लिए अधिक समझ में आता है text()


यह शीर्ष उत्तर क्यों नहीं है? बहुत अच्छा स्पष्टीकरण बहुत बहुत धन्यवाद!
गियानलुक्का

1
कुछ ऐसा जो हर प्रकार के तत्व के साथ काम करता है? मैं नहीं जान सकता कि क्या पाठ एक बटन के अंदर है, एपी, एक डिव, एक स्पैन आदि
एंड्रिया बिसेलो

5
@AndreaBisello आप //*[...]इसके बजाय उपयोग कर सकते हैं ।
थॉमस डोंडॉर्फ

90

आप पृष्ठ के साथ XPath चयनकर्ता का उपयोग कर सकते हैं । $ x (अभिव्यक्ति) :

const linkHandlers = await page.$x("//a[contains(text(), 'Some text')]");

if (linkHandlers.length > 0) {
  await linkHandlers[0].click();
} else {
  throw new Error("Link not found");
}

एक संपूर्ण उदाहरण के लिए clickByTextइस जिस्ट में देखें । यह उद्धरण से बचने का ख्याल रखता है, जो कि XPath अभिव्यक्तियों के साथ थोड़ा मुश्किल है।


बहुत बढ़िया - मैंने इसे अन्य टैग के लिए करने की कोशिश की, लेकिन यह काम नहीं कर सकता। (ली, एच 1, ...) आप ऐसा कैसे करेंगे?
रूनी जेप्पेसेन

3
बदलें @RuneJeppesen //a[containsसाथ //*[containsकिसी भी तत्व को ही नहीं, एक लंगर (चयन करने के लिए a) तत्व।
यूनिक्समनकी

14

आप पाठ सामग्री द्वारा फ़िल्टर किए गए page.evaluate()तत्वों से प्राप्त तत्वों को क्लिक करने के लिए भी उपयोग कर सकते हैं document.querySelectorAll():

await page.evaluate(() => {
  [...document.querySelectorAll('.elements button')].find(element => element.textContent === 'Button text').click();
});

वैकल्पिक रूप से, आप page.evaluate()इसके पाठ सामग्री के आधार पर किसी तत्व को क्लिक करने के लिए उपयोग कर सकते हैं document.evaluate()और एक्सपीथ एक्सप्रेशन का उपयोग कर सकते हैं :

await page.evaluate(() => {
  const xpath = '//*[@class="elements"]//button[contains(text(), "Button text")]';
  const result = document.evaluate(xpath, document, null, XPathResult.ANY_TYPE, null);

  result.iterateNext().click();
});

13

"जैसे: (पाठ)" में उन्नत सीएसएस चयनकर्ताओं का उपयोग करने में सक्षम होने के लिए त्वरित समाधान किया गया है।

इसलिए इस पुस्तकालय का उपयोग करके आप कर सकते हैं

const select = require ('puppeteer-select');

const element = await select(page).getElement('button:contains(Button text)');
await element.click()

4

यहाँ मेरा समाधान है:

let selector = 'a';
    await page.$$eval(selector, anchors => {
        anchors.map(anchor => {
            if(anchor.textContent == 'target text') {
                anchor.click();
                return
            }
        })
    });


0

पाठ चयनकर्ता या कॉम्बीनेटर विकल्प के लिए कोई समर्थित सीएसएस चयनकर्ता सिंटैक्स नहीं है, इसके लिए मेरा काम आसपास होगा:

await page.$$eval('selector', selectorMatched => {
    for(i in selectorMatched)
      if(selectorMatched[i].textContent === 'text string'){
          selectorMatched[i].click();
          break;//Remove this line (break statement) if you want to click on all matched elements otherwise the first element only is clicked  
        }
    });

0

सुझाव देने वाले कई उत्तर हैं, containsलेकिन ओपी के उपयोग के मामले को देखते हुए मुझे इस अभद्रता के लिए कोई प्रेरणा नहीं दिखती है, जो सभी दिखावे से, एक लक्ष्य स्ट्रिंग "Button text"और एक तत्व के साथ एक सटीक मेल है <button>Button text</button>

मैं अधिक सटीक का उपयोग करना पसंद करूंगा [text()="Button text"], जो बटन के कहने पर झूठे सकारात्मक से बचता है <button>Button text and more stuff</button>:

const [el] = await page.$x('//*[@class="elements"]//a[text()="Button text"]');
el && (await el.click());

यह इस उत्तर के विपरीत परिदृश्य का अनुमान लगाता है जो संभव के रूप में अनुमेय होने का प्रयास करता है।

कई जवाब भी .elementsमूल वर्ग की आवश्यकता को याद किया ।


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.