【问题标题】:How to check if a web element is visible如何检查网页元素是否可见
【发布时间】:2014-04-22 13:29:27
【问题描述】:

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

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 方法和获取文本属性执行 http 请求来检索此类信息。因此,当页面上有许多链接或您必须多次执行此操作时,事情会变得非常缓慢。

另一方面,BeautifulSoup 可以在获得页面源后零时间执行这些解析操作。但我不知道该怎么做。

【问题讨论】:

  • 我认为你能做的最好的就是检查美丽汤标签的style属性并解析该值以查看其中是否有类似的display:none
  • 不幸的是,Beautifulsoup 是一个 html 解析器,而不是浏览器,所以它对如何渲染页面一无所知。我认为你必须坚持使用 Selenium。
  • pyself,我很确定@fasouto 是对的。 beautifulsoup 实际上并没有渲染任何东西,如果你阅读 selenium 文档,它会自动化 BROWSERS.. 而不仅仅是纯 HTML。如果你真的想这样做,我认为你必须坚持使用 selenium 来做这件事。
  • 元素被内联、链接或内部 CSS 隐藏(input 除外)。或者用JS隐藏。然后你有其他不可见的东西,比如白色背景上的白色文本。你到底想检查什么?只有 CSS display:none?比您需要使用 tinycss 解析 all 样式表并查看规则是否与元素匹配。如果找到匹配项,请检查应用了哪些样式。困难在于级联部分。此外,如果隐藏了父级,则隐藏了子级。因此,您必须检查该元素的所有父元素是否也可见......或者只使用 Selenium。

标签: python selenium web beautifulsoup


【解决方案1】:

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、脚本和动态 DOM 更改。另一方面,Selenium 确实会告诉您一个元素是否正在被渲染,并且通常是通过给定浏览器中的可访问性 API 来实现的。您必须决定是否值得追求速度而牺牲准确性。祝你好运! :-)

【讨论】:

    【解决方案2】:

    试试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")')
    

    【讨论】:

      猜你喜欢
      • 2017-01-01
      • 2012-07-08
      • 1970-01-01
      • 2020-08-06
      • 2012-04-21
      • 2011-02-08
      • 2010-10-03
      • 2023-03-04
      • 1970-01-01
      相关资源
      最近更新 更多