如何检查Web元素是否可见

时间:2014-03-17 11:08:08

标签: python selenium web beautifulsoup

我正在使用带有BeautifulSoup4的Python,我需要检索页面上的可见链接。鉴于此代码:

soup = BeautifulSoup(html)
links = soup('a')

我想创建一个方法 is_visible ,用于检查页面上是否显示链接。

使用Selenium

的解决方案

由于我也在使用Selenium,我知道存在以下解决方案:

from selenium.webdriver import Firefox

firefox = Firefox()
firefox.get('https://google.com')
links = firefox.find_elements_by_tag_name('a')

for link in links:
    if link.is_displayed():
        print('{} => Visible'.format(link.text))
    else:
        print('{} => Hidden'.format(link.text))

firefox.quit()

绩效问题

不幸的是 is_displayed 方法并且获取text属性执行http请求以检索此类信息。因此,当页面上有许多链接或者您必须多次执行此操作时,事情会变得非常慢。

另一方面,一旦获得页面源,BeautifulSoup可以在零时间内执行这些解析操作。但我无法弄清楚如何做到这一点。

2 个答案:

答案 0 :(得分:0)

AFAIK,BeautifulSoup只会帮助您解析HTML文档的实际标记。如果这就是您所需要的,那么您可以这样做(是的,我已经知道它并不完美):

from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc)


def is_visible_1(link):
    #do whatever in this function you can to determine your markup is correct
    try:
        style = link.get('style')
        if 'display' in style and 'none' in style:#or use a regular expression
            return False
    except Exception:
        return False
    return True

def is_visible_2(**kwargs):
    try:
        soup = kwargs.get('soup', None)
        del kwargs['soup']
        #Exception thrown if element can't be found using kwargs
        link = soup.find_all(**kwargs)[0]
        style = link.get('style')
        if 'display' in style and 'none' in style:#or use a regular expression
            return False
    except Exception:
        return False
    return True


#checks links that already exist, not *if* they exist
for link in soup.find_all('a'):
    print(str(is_visible_1(link)))

#checks if an element exists
print(str(is_visible_2(soup=soup,id='someID')))

BeautifulSoup 不会考虑其他会告诉您元素是否可见的方,例如:CSS,Scripts和动态DOM更改。另一方面,Selenium会告诉您元素实际上是否正在呈现,并且通常通过给定浏览器中的可访问性API来实现。你必须决定牺牲速度的准确性是否值得追求。祝好运! : - )

答案 1 :(得分:0)

尝试使用find_elements_by_xpathexecute_script

from selenium import webdriver

driver = webdriver.Chrome()

driver.get("https://www.google.com/?hl=en")
links = driver.find_elements_by_xpath('//a')

driver.execute_script('''
    var links = document.querySelectorAll('a');

    links.forEach(function(a) {
        a.addEventListener("click", function(event) {
            event.preventDefault();
        });
    });
''')

visible = []
hidden = []
for link in links:
    try:
        link.click()
        visible.append('{} => Visible'.format(link.text))
    except:
        hidden.append('{} => Hidden'.format(link.get_attribute('textContent')))

    #time.sleep(0.1)

print('\n'.join(visible))
print('===============================')
print('\n'.join(hidden))
print('===============================\nTotal links length: %s' % len(links))

driver.execute_script('alert("Finish")')