Selenium Webdriver'da (Python) belirli metin içeren bir öğeyi nasıl bulurum?


260

Selenium ile karmaşık bir javascript arabirimini (Python arabirimini kullanarak ve birden çok tarayıcıyı kullanarak) test etmeye çalışıyorum. Formun düğmeleri bir dizi var:

<div>My Button</div>

"Düğmem" (veya "düğmem" veya "düğme" gibi büyük / küçük harfe duyarlı olmayan kısmi eşleşmeler temelinde düğmeler arayabilmek istiyorum)

Bunu inanılmaz derecede zor buluyorum, ne kadar bariz bir şeyi kaçırmışım gibi hissediyorum. Şimdiye kadar sahip olduğum en iyi şey:

driver.find_elements_by_xpath('//div[contains(text(), "' + text + '")]')

Ancak bu büyük / küçük harfe duyarlıdır. Denediğim diğer bir şey de sayfadaki tüm div'leri yinelemek ve element.text özelliğini kontrol etmektir. Bununla birlikte, formun her durumunu aldığınızda:

<div class="outer"><div class="inner">My Button</div></div>

div.outer ayrıca metin olarak "Düğmem" e sahiptir. Bunu düzeltmek için div.outer'ın div.inner'ın üst öğesi olup olmadığını aramaya çalıştım, ancak bunu nasıl yapacağınızı anlayamadım (element.get_element_by_xpath ('..') bir öğenin üst öğesini döndürüyor, ancak testler div.outer'a eşit değildir). Ayrıca, sayfadaki tüm öğeler arasında yineleme yapmak, en azından Chrome web sürücüsünü kullanarak gerçekten yavaş görünüyor.

Fikirler?

Edit: Bu soru biraz belirsiz çıktı. Burada daha spesifik bir sürüm istendi (ve cevaplandı): Selenium WebDriver'da (Python api aracılığıyla) bir alt öğenin metni alt öğe metni eklenmeden nasıl alınır?


Mevcut cevaplar benim için işe yaramadı. Bunu yaptı: sqa.stackexchange.com/a/2486
alejandro

Yanıtlar:


328

Takip etmeyi dene:

driver.find_elements_by_xpath("//*[contains(text(), 'My Button')]")

3
Cevabınız için teşekkür ederim, ihtiyacım olanın% 50'siydi (beni başlattı). Geldiğim form şudur "(// * [içerir (metin (), '" + metin + "')] | // * [@ değer = '" + metin + "'])" yalnızca öğe düğümlerinin içinde değil, aynı zamanda metni 'değer' özniteliği ile ayarlanan giriş öğelerinin içinde de verilen, yani <düğme değeri = "Düğmem" />. Unutmayın, değer sadece metni içermez, sıkı eşleme olmalıdır.
Ivan Koshelev

9
Ayrıca diğer arama motoru ziyaretçileri için bahsetmeye değer: Eğer bir bağlantı arıyorsanız, yöntemler find_element(s)_by_link_textve find_element(s)_by_partial_link_textyöntemler vardır
Dan Passaro

3
Metin dinamikse ne olur? Yani, tırnak işaretleri içerebilir. Bu çözümü çözmez mi?
IcedDante

3
Belirli isimleri aramak bunu bozuyor gibi görünüyor. Bir örnek için aşağıdakileri alın: "// * [içerir (text (), '" + kullanıcı adı + "')]" eğer kullanıcıadı = "O'Reilly"; o zaman xpath geçersiz olur. Bunun etrafında bir yol var mı?
Sakamoto Kazuma

Hedef metnin birden fazla satırı olduğunda işe yaramıyor gibi görünüyor.
Shawn

29

şöyle bir xpath deneyebilirsiniz:

'//div[contains(text(), "{0}") and @class="inner"]'.format(text)

Teşekkürler ... böylece bu içsel olanı dıştan ayırt etmeye yardımcı olur, ancak aslında xpath ile iyi çalışır, sadece tüm div'larda yinelenen bu problemi yaşıyordum. Xpath ile ilgili sorunum, nasıl büyük / küçük harfe duyarsız hale getiremediğimi anlayamıyorum?
josh

2
xpath 2.0'ın küçük harf işlevi vardır, bu nedenle şu şekilde çalışır: '// div [şunu içerir (küçük harf (metin ()), "{0}")]'. biçim (metin)
andrean

Teşekkürler! Ancak, benim anlayışım xpath 2.0 büyük tarayıcılarda desteklenmiyor ...
josh

selenium xpath ifadelerini doğrudan tarayıcının kendi yöntemleriyle değerlendirir, bu nedenle selenium ile hangi tarayıcıyı kullandığınıza bağlıdır. genellikle sadece 6,7 ve 8 xpath 2.0'ı desteklememelidir.
andrean

.formatTutulmamda tanınmıyor. hata veriyor. herhangi bir fikir, neden?
anujin

16

Sayfa Nesnesi Deseni ile de kullanabilirsiniz, örneğin:

Bu kodu deneyin:

@FindBy(xpath = "//*[contains(text(), 'Best Choice')]")
WebElement buttonBestChoice;

13

// * herhangi bir HTML etiketi arayacaktır. Button ve div etiketi için bazı metinler ortaksa ve // ​​* kategoriler ise, beklendiği gibi çalışmaz. Herhangi bir belirli seçmeniz gerekiyorsa, HTML Öğesi etiketi bildirerek alabilirsiniz. Sevmek:

driver.find_element_by_xpath("//div[contains(text(),'Add User')]")
driver.find_element_by_xpath("//button[contains(text(),'Add User')]")

5

İlginçtir ki neredeyse tüm cevaplar xpath'in işlevi etrafında dönüyor ve OP'nin sorusunun aksine contains()büyük / küçük harfe duyarlı olduğu gerçeğini ihmal ediyor .
Büyük / küçük harf duyarsızlığına ihtiyacınız varsa, xpath 1.0'da (çağdaş tarayıcıların desteklediği sürüm) elde edilebilir , ancak hoş değil - translate()işlevini kullanarak . Bir çeviri tablosu kullanarak bir kaynak karakteri istenen forma çevirir.

Tüm büyük harfli karakterlerden oluşan bir tablo oluşturmak, düğüm metnini etkin bir şekilde alt () formuna dönüştürerek büyük / küçük harfe duyarlı olmayan eşleştirmeye olanak tanır (işte burada ayrıcalık vardır) :

[
  contains(
    translate(text(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),
    'my button'
  )
]
# will match a source text like "mY bUTTon"

Tam python çağrısı:

driver.find_elements_by_xpath("//*[contains(translate(text(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZЙ', 'abcdefghijklmnopqrstuvwxyzй'), 'my button')]")

Doğal olarak bu yaklaşımın dezavantajları vardır - verildiği gibi, sadece latin metin için işe yarayacaktır; unicode karakterleri kapsamak istiyorsanız - bunları çeviri tablosuna eklemeniz gerekir. Bunu yukarıdaki örnekte yaptım - son karakter Kiril sembolüdür "Й".


Tarayıcıların xpath 2.0 ve üstü sürümlerini (🤞, ancak yakın zamanda gerçekleşmeyecek ☹️) desteklediği bir dünyada yaşıyor olsaydık,lower-case() (henüz tam olarak yerel ayarlara uygun olmayan) işlevleri ve matches(regex aramaları için ) duyarsız ( 'i') bayrağı).


4

Sağladığınız HTML'de:

<div>My Button</div>

Metin My Buttonise innerHTMLve kolayca kullanabilmesi etrafında hiçbir boşlukları var text()aşağıdaki gibi:

my_element = driver.find_element_by_xpath("//div[text()='My Button']")

Not : text()bağlam düğümünün tüm metin düğümü alt öğelerini seçer


Ön / arka boşluklu metin

Başlangıçta boşluk içeren ilgili metni kaldırın :

<div>   My Button</div>

veya sonunda:

<div>My Button   </div>

veya her iki uçta:

<div> My Button </div>  

Bu durumlarda 2 seçeneğiniz vardır:

  • contains()İlk bağımsız değişken dizesinin ikinci bağımsız değişken dizesini içerip içermediğini ve boolean true veya false değerini aşağıdaki gibi döndürüp döndürmediğini belirleyen işlevi kullanabilirsiniz :

    my_element = driver.find_element_by_xpath("//div[contains(., 'My Button')]")
  • Kullanabilirsiniz normalize-space()aşağıdaki gibi tek bir boşlukla gelen ve bir dizgeden boşluk arka şeritler fonksiyon, bir boşluk karakteri yerine geçer dizileri ve bir dizge verir:

    driver.find_element_by_xpath("//div[normalize-space()='My Button']]")

Değişken için xpath

Metin kullanmak kullanabileceğiniz bir değişkendir:

foo= "foo_bar"
my_element = driver.find_element_by_xpath("//div[.='" + foo + "']")

1
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[contains(text(), 'YourTextHere')]")));
    assertNotNull(driver.findElement(By.xpath("//*[contains(text(), 'YourTextHere')]")));
    String yourButtonName=driver.findElement(By.xpath("//*[contains(text(), 'YourTextHere')]")).getAttribute("innerText");
    assertTrue(yourButtonName.equalsIgnoreCase("YourTextHere"));

1

Benzer sorun: Bul <button>Advanced...</button>

Belki bu size bazı fikirler verecektir (lütfen konsepti Java'dan Python'a aktarın):

wait.until(ExpectedConditions.elementToBeClickable(//
    driver.findElements(By.tagName("button")).stream().filter(i -> i.getText().equals("Advanced...")).findFirst().get())).click();


-19

Bunu dene. Bu çok kolay:

driver.getPageSource().contains("text to search");

Bu gerçekten benim için selenyum web sürücüsünde çalıştı.


9
Metin JavaScript tarafından oluşturulmuşsa çalışmaz.
palacsint

2
Bu, kontrol etmenin çok bir yoludur, çünkü sayfanın tüm içeriğini kablo üzerinden aktarıyorsunuz. Çok küçük sayfalar için bu kabul edilebilir ancak çok büyük sayfalar için dosyanın tüm içeriğini aktarır ve sunucu tarafında kontrol edersiniz. Daha iyi bir yaklaşım, istemci tarafında xpath, javascript veya css ile yapmak olacaktır.
thomas.han

Tarayıcıyı işlemek için tüm sayfa kaynağının tel üzerinden aktarılması gerektiğini düşünür müydüm?
René

3
Josh, metnin sayfanın kaynağında bulunup bulunmadığını sınamak için öğeyi metinle nasıl bulacağını soruyor.
Cedric

1
Her şeyin gerekli olduğu durumlarda, bir sayfada statik bir metin bulmak bu çözüm yeterince iyidir. (Benim durumumda yardımcı oldu).
Karlth
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.