python - 如何通过同时调用不同的 css 选择器来抓取 Selenium/Python 中的元素?
问题描述
我正在尝试通过集成多个 css 选择器来选择网页中加载的帖子的标题。看下面我的过程:
加载相关库
import time
from selenium import webdriver
from webdriver_manager.firefox import GeckoDriverManager
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
然后加载我要分析的内容
options = Options()
options.set_preference("dom.push.enabled", False)
browser = webdriver.Firefox(options=options)
browser.get("https://medium.com/search")
browser.find_element_by_xpath("//input[@type='search']").send_keys("international development",Keys.ENTER)
time.sleep(5)
scrolls = 2
while True:
scrolls -= 1
browser.execute_script("window.scrollTo(0, document.body.scrollHeight)")
time.sleep(5)
if scrolls < 0:
break
然后分别获取每个选择器的内容,调用 css_selector
titles=browser.find_elements_by_css_selector("h3[class^='graf']")
TitlesList = []
for names in titles:
names.text
TitlesList.append(names.text)
times=browser.find_elements_by_css_selector("time[datetime^='2016']")
Times = []
for names in times:
names.text
Times.append(names.text)
到目前为止一切正常……现在试图将它们结合在一起,目的是确定 2016 年的唯一选择
choices = browser.find_elements_by_css_selector("time[datetime^='2016'] and h3[class^='graf']")
browser.quit()
在最后一个片段中,我总是得到一个空列表。
所以我想知道 1)如何通过同时考虑不同的 css_selector 作为选择条件来选择多个元素 2)如果在多个条件下查找的语法与使用不同的方法(如 css_selector 或 x_paths 和 3)链接元素相同) 如果有一种方法可以获取通过调用多个 css 选择器识别的元素的文本,如下所示:
[pair.text for pair in browser.find_elements_by_css_selector("h3[class^='graf']") if pair.text]
谢谢
解决方案
首先,我认为你想要做的是获得任何有时间在 2016 年发布的标题,对吗?
您正在使用 CSS 选择器"time[datetime^='2016'] and h3[class^='graf']"
,但这不起作用,因为它的语法无效(and
无效)。另外,这是 2 个不同的元素,CSS 选择器只能找到 1 个元素。在您的情况下,要从另一个元素添加条件,请使用父元素之类的公共元素。
我已经检查了该站点,这是您需要查看的 HTML(如果您尝试使用 2016 年发布的标题)。这是最小的 HTML 部分,可以帮助您确定需要获取的内容。
<div class="postArticle postArticle--short js-postArticle js-trackPostPresentation" data-post-id="d17220aecaa8"
data-source="search_post---------2">
<div class="u-clearfix u-marginBottom15 u-paddingTop5">
<div class="postMetaInline u-floatLeft u-sm-maxWidthFullWidth">
<div class="u-flexCenter">
<div class="postMetaInline postMetaInline-authorLockup ui-captionStrong u-flex1 u-noWrapWithEllipsis">
<div
class="ui-caption u-fontSize12 u-baseColor--textNormal u-textColorNormal js-postMetaInlineSupplemental">
<a class="link link--darken"
href="https://provocations.darkmatterlabs.org/reimagining-international-development-for-the-21st-century-d17220aecaa8?source=search_post---------2"
data-action="open-post"
data-action-value="https://provocations.darkmatterlabs.org/reimagining-international-development-for-the-21st-century-d17220aecaa8?source=search_post---------2"
data-action-source="preview-listing">
<time datetime="2016-09-05T13:55:05.811Z">Sep 5, 2016</time>
</a>
</div>
</div>
</div>
</div>
</div>
<div class="postArticle-content">
<a href="https://provocations.darkmatterlabs.org/reimagining-international-development-for-the-21st-century-d17220aecaa8?source=search_post---------2"
data-action="open-post" data-action-source="search_post---------2"
data-action-value="https://provocations.darkmatterlabs.org/reimagining-international-development-for-the-21st-century-d17220aecaa8?source=search_post---------2"
data-action-index="2" data-post-id="d17220aecaa8">
<section class="section section--body section--first section--last">
<div class="section-divider">
<hr class="section-divider">
</div>
<div class="section-content">
<div class="section-inner sectionLayout--insetColumn">
<h3 name="5910" id="5910" class="graf graf--h3 graf--leading graf--title">Reimagining
International Development for the 21st Century.</h3>
</div>
</div>
</section>
</a>
</div>
</div>
两者time
都h3
在一个div
大类中postArticle
。div
文章包含发表时间和标题,因此获取2016 年发表的整篇文章是否有意义?
使用 XPATH 更强大且更易于编写:
- 这将获得所有
div
包含类名的文章postArticle--short
:article_xpath = '//div[contains(@class, "postArticle--short")]'
- 这将获得所有
time
包含类名的标签2016
://time[contains(@datetime, "2016")]
让我们将它们结合起来。我想获取div
包含time
类名标签的文章2016
:
article_2016_xpath = '//div[contains(@class, "postArticle--short")][.//time[contains(@datetime, "2016")]]'
article_element_list = driver.find_elements_by_xpath(article_2016_xpath)
# now let's get the title
for article in article_element_list:
title = article.find_element_by_tag_name("h3").text
我还没有测试代码,只有 xpath。您可能需要调整代码以在您身边工作。
顺便说一句,使用find_element...
不是一个好主意,尝试使用显式等待:https ://selenium-python.readthedocs.io/waits.html
这将帮助您避免愚蠢time.sleep
的等待并提高您的应用程序性能,并且您可以很好地处理错误。
仅find_element...
在已经找到元素并且需要在其中找到子元素时使用。比如这种情况下如果要查找文章,我会通过显式等待查找,然后在找到元素后,我会使用find_element...
查找子元素h3
。
推荐阅读
- javascript - vues js在重定向上传递对象
- angular - 根据用户从下拉列表中所做的选择填充表单字段
- java - 在构建自己的 SSLContext (Java) 时`无法找到有效的证书路径...`
- amazon-web-services - 使用 APIGatewayV2HTTPRequest 时接收空标头的 Lambda 函数
- android - 回收站视图无法访问(Android Studio)
- c - 如何使用串行通信将数据从 atmega328p 串行发送到 pc?
- typescript - 基于类泛型类型的可选类构造函数属性
- python - 如何在硒网络驱动程序python中切换链接每个循环
- javascript - 从数组中获取最新的次要版本数组
- html - 在另一个样式中设置一个元素的样式作为伪元素的第一行