【发布时间】:2021-03-31 08:24:41
【问题描述】:
我们正在尝试从 job website 的 DOM 中解析 href 属性。我们希望为每个工作获得一个href。
我们通常使用 CSS 路径并将它们传递给 Selenium 的 find_elements_by_css 方法。
很遗憾,我们注意到浏览器插件SelectorGadget 无法为我们提供 CSS 路径。我们继续使用 Google Chrome (ctrl+shift+c) 的 CSS 路径。 Chrome 可以提取路径,但 Selenium 和 BeautifulSoup 都不能使用这些路径。
在多次尝试使用不同的类和标签提取元素失败后,我们认为我们的方法或网站完全有问题。我们假设 Selenium 和 BeautifulSoup 出于某种原因无法解析所需的元素? DOM 中的iframe 标记是否会成为错误源(请参阅此SO question)?是什么导致解析失败,有没有办法解决这个问题?与网站相关的问题源也可以解释为什么 SelectorGadget 无法首先获得路径。我们的结论是使用正则表达式来提取我们需要的href 属性。这只是万不得已的解决方案。
对于讲德语的人,请注意目标元素中存在拼写错误:<div class="stellenagebot">。请不要让自己被这些混淆(就像我们所做的那样)。
BeautifulSoup 不走运:
import re
import requests
from bs4 import BeautifulSoup
url = 'https://www.artemiskliniken.de/Karriere/%C3%84rzte/'
page = requests.get(url)
soup = BeautifulSoup(page.text, 'html.parser')
print(soup.prettify())
# Out: ...
#<div class="col-md-4 wow fadeInUp">
# <div class="stellenagebot">
# <h3>
# Facharzt (m/w/d) für Augenheilkunde in Voll- oder Teilzeit
# </h3>
# <h4>
# Erfurt
# </h4>
# <a class="btn btn-default" href="/Stellenangebot/Facharzt_Augenheilkunde_Erfurt/">
# Mehr
# </a>
# </div>
#</div>
#<div class="col-md-4 wow fadeInUp">
# <div class="stellenagebot">
# <h3>
# Facharzt (m/w/d) für Augenheilkunde in Voll- oder Teilzeit
# </h3>
# <h4>
# Eschwege
# </h4>
# <a class="btn btn-default" href="/Stellenangebot/Facharzt_Augenheilkunde_Eschwege/">
# Mehr
# </a>
# </div>
#</div>
# ...
print(soup.find_all('.stellenagebot'))
# Out: []
print(soup.find_all(string=re.compile("Stellenangebot")))
# ['Stellenangebote Facharzt für Augenheilkunde und Karrierewege für Ärzte', '<h3>Zur Verstärkung unseres Teams suchen wir:</h3>\n\n<p class="hyphenate" lang="de"> </p>\n\n<div id=\'jobauflistung\' class=\'row\'><div class=\'col-md-4 wow fadeInUp\'><div class="stellenagebot">\n<h3>Facharzt (m/w/d) für Augenheilkunde in Voll- oder Teilzeit</h3>\n\n<h4>Aachen</h4>\n<a class="btn btn-default" href="/Stellenangebot/Facharzt_Augenheilkunde_Aachen/">Mehr</a></div></div><div class=\'col-md-4 wow fadeInUp\'><div class="stellenagebot">\n<h3>Facharzt (m/w/d) fü
# ...
# ></div>\n</div>\n</div>\n</div>\n</footer>\n</div><!-- AUF ALLEN SEITEN IN DEN BODY-TAG EINFÜGEN ']
print(len(soup.find_all(string=re.compile("Stellenangebot"))))
# Out: 2
Selenium 也没有运气:
from selenium import webdriver
from job_scraper.configuration import CHROMEDRIVER_VERSION, ROOT_PATH, \
CHROME_OPTIONS
driver = webdriver.Chrome(
ROOT_PATH / f'assets/chrome_drivers/{CHROMEDRIVER_VERSION}',
options=CHROME_OPTIONS
)
driver.maximize_window()
driver.get(url)
driver.find_elements_by_css_selector('.stellenagebot')
# Out: []
【问题讨论】:
-
如果元素在
iframe中,则它被视为单独的页面,您必须加载它。Selenium甚至有switch_to.frame(...)来加载iframe中的内容。BeatifulSoup不会解析iframe中的元素,因为它不是当前页面的一部分,您必须从iframe获取 url 并使用requests加载它 -
当我在网络浏览器中检查页面时,我在评论中看到
stellenagebot仅在 HTML 中<!-- .... -->所以BeautifulSoup和Selenium不会将其视为 HTML,而是将其视为评论中的普通字符串。所以它可能必须从comment获取文本并单独解析它。 -
此页面在表格中使用 JavaScript - 所以我在显示的表格中看不到任何
href,因为 URL 隐藏在 JavaScript 中的某处。我只在 HTML 的评论中看到href。 -
感谢您提供的背景信息! @furas
标签: python html selenium web-scraping beautifulsoup