我正在使用带有BeautifulSoup4的Python,我需要检索页面上的可见链接。鉴于此代码:
soup = BeautifulSoup(html)
links = soup('a')
我想创建一个方法 is_visible ,用于检查页面上是否显示链接。
由于我也在使用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可以在零时间内执行这些解析操作。但我无法弄清楚如何做到这一点。
答案 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_xpath
和execute_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")')