介绍
本文介绍如何获取元素以使用 Selenium 进行抓取以及如何调试。
关于本文环境 Selenium 为 4.4,浏览器使用 chrome。
如何搭建 Selenium 环境请参考之前写的让 Python 做日常工作:用 Selenium 自动化考勤处理。
检查假设
如果您的假设不正确,您将浪费时间进行调试。
如果你正在抓取并得到NoSuchElementException 异常,让我们检查一下我们的假设。
网址正确
如果您收到NoSuchElementException 异常,请确保您尝试从中获取元素的页面的 URL 是正确的。
HTTP 重定向例如,很有可能无法获得预期的响应。
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"[id="app"]"}
Selenium 提供了current_url 方法。
参考:获取当前网址
您可以使用current_url 方法来确定URL。
以下是current_url 的结果与base_url 定义的URL 比较不正确时输出异常的示例。
try:
if browser.current_url == f'{base_url}':
<URLが正しい場合の処理>
else:
raise BatchError('failure')
finally:
pass
如果无法解析名称,将输出以下错误消息。
如果在可以解析URI方案的主机名时输出NoSuchElementException消息,则可能是路径不正确。
selenium.common.exceptions.WebDriverException: Message: unknown error: net::ERR_NAME_NOT_RESOLVED
您尝试获取的元素名称是正确的
如果您尝试获取的元素名称错误,例如拼写错误,则会输出异常NoSuchElementException。
例如,我以为我在 CSS 选择器中指定了 'app',但我不小心输入了一个太多的 p。
element = browser.find_element(By.ID, 'appp')
因为元素名称不存在,所以输出NoSuchElementException 异常。
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"[id="appp"]"}
Selenium 提供了is_enabled() 方法。
参考:有关网络元素的信息
您可以使用is_enabled() 方法来确定元素。
如果元素有效,下面的示例将打印element: True。
element = browser.find_element(By.ID, 'app').is_enabled()
print(f'element: {element}')
获取元素需要知道的事情
了解定位器位置对于通过抓取检索元素很重要。
了解定位器移动
find_element 和 find_elements 被提供为用于查找元素的基本方法。
定位器的移动和方法返回值的数据类型不同,所以要了解规范并相应使用。
find_element 方法获取 DOM 中与定位器匹配的第一个元素。
element = browser.find_element(By.ID, 'wrapper')
print(f'element: {element}')
print(type(element))
上面的输出如下。
element: <selenium.webdriver.remote.webelement.WebElement (session="83637704440c02c40230f7f3c432a776", element="3962b35a-d2ae-4517-92bf-9d4d15733494")>
<class 'selenium.webdriver.remote.webelement.WebElement'>
find_elements 方法查找多个元素并将它们返回到一个列表中。
element = browser.find_elements(By.ID, 'wrapper')
print(f'element: {element}')
print(type(element))
可以看到返回的列表如下。
element: [<selenium.webdriver.remote.webelement.WebElement (session="b6272bed38cd78b07fdcba2f7fafbb4c", element="14ba230f-78b6-4e8f-bc08-ccd001d950f4")>]
<class 'list'>
参考:搜索网络元素
总之,find_element 方法只检索在搜索中找到的第一个元素。要获取多个元素,请使用find_elements 方法。
XPath 和 CSS 选择器
XML 路径语言(少于,XPath) 很有用,例如,当您要检索的元素没有合适的 ID 时。
基于 XPath 的机制,它是从根目录开始的绝对路径引用的,所以如果网站发生变化,可能无法获取。
当唯一 id 不可用时,编写良好的 CSS 选择器是查找元素的好方法。 XPath 的工作方式类似于 CSS 选择器,但语法复杂且通常难以调试。 XPath 非常灵活,但浏览器供应商通常不会对其进行性能测试,而且速度往往很慢。
参考:使用定位器的提示
桌子
硒是桌子也可以获得元素。
与BeautifulSoup一样,从包含获取到的table元素的对象中tr元素和时间提取元素。
对象以列表类型存储,因此您可以通过执行for语句来获取tr 元素。以下是使用
appID 缩小范围并检索表元素数据的示例。# id element = browser.find_element(By.ID, 'app') # table table = element.find_element(By.TAG_NAME, 'table') # tr tr_list = table.find_elements(By.TAG_NAME, 'tr')从作为一组检索行的
tr_list对象中,指定作为单元格数据的td_list的索引,然后提取它。
如果表格有两个单元格数据,请按如下方式指定索引。table_list = [] for index, row in enumerate(tr_list): # ヘッダはスキップ if index == 0: continue # td td_list = row.find_elements(By.TAG_NAME, 'td') td_dict = {'name': td_list[0].text, 'price': td_list[1].text} table_list.append(td_dict)纽扣
根据网站的结构,通过爬取连续获取数据的难易程度不同。
对于通过如下所示在请求标头中指定查询参数来执行 HTTP 通信的站点,我认为这很容易,因为它只会增加page=的值。https://<WebサイトのURL>/list/?page=2由SPA等组成的网站。纽扣对于内容根据客户端移动(例如元素)而以不同方式加载和显示的站点,需要加载内容的说明。
因此,在由如下所示的按钮元素组成的内容的情况下,除非单击表示页码的数字,否则无法显示下一个数据。
作为一种解决方案,您可以使用上面介绍的
is_enabled()方法来创建逻辑,例如如果按钮存在则加载下一个内容,如果不存在则退出页面。在下面的示例中,由 table 元素组成的内容的 CSS 选择器第n个孩子递增以确定接下来要加载的按钮。
如果button.is_enabled()结果为True,单击按钮加载下一个内容。flag = True num = 2 while flag is True: # id element = browser.find_element(By.ID, 'app') # table table = element.find_element(By.TAG_NAME, 'table') # tr tr_list = table.find_elements(By.TAG_NAME, 'tr') try: if flag is True: num += 1 button = element.find_element(By.CSS_SELECTOR, "CSSセレクタのパス > li:nth-child("+(str(num))+") > button") if button.is_enabled() is True: button.click() else: flag = False except common.exceptions.NoSuchElementException as e: continue框架和 iframe
我想你可能会在遗留系统等中看到它。内嵌框架同样,您可以通过指定和访问实体来进行抓取。
其他
如何使用个人资料
默认情况下,ChromeDriver 会为每个会话创建一个新的临时配置文件。
如果想接管session等登录信息,可以通过Chrome的用户配置文件来解决。下面是使用 Chrome 的用户配置文件作为驱动程序选项的示例。
profile_path可以通过打开 Chrome 并访问chrome://version/找到。from selenium import webdriver options = webdriver.chrome.options.Options() profile_path = '/Users/<Your Name>/Library/Application Support/Google/Chrome/Default' options.add_argument('--user-data-dir=' + profile_path)参考:选项
有关驱动程序选项的更多信息,请参阅 ChromeDriver 的常见用例你可以检查更多。
尝试/除
如果你因为找不到元素而得到
NoSuchElementException异常,并且想要继续而不停止,你可以使用common.exceptions.NoSuchElementException来捕获异常。from selenium import common try: <何らかの処理> except common.exceptions.NoSuchElementException as e: continue睡眠处理
即使元素存在,在渲染耗时较长时可能会出现
NoSuchElementException,可能无法获取到元素。作为对策,您可以使用标准模块的
time.sleep函数轻松实现睡眠处理,但是 Selenium 有显式等待什么时候,隐式等待有两种方法称为参考:支持
僵尸进程
在运行 Selenium 时未能正确终止
quit()会使驱动程序的僵尸进程在后台运行。
如果服务器使用 cron 等定期运行它,内存不会被释放,造成不必要的内存消耗。hoge 68212 0.0 0.0 37946300 6680 s002 S 4:16PM 0:05.48 /Users/hoge/.wdm/drivers/chromedriver/mac64/106.0.5249/chromedriver --port=61942 hoge 67990 0.0 0.0 37946300 6668 s002 S 4:04PM 0:02.43 /Users/hoge/.wdm/drivers/chromedriver/mac64/106.0.5249/chromedriver --port=58852 hoge 67539 0.0 0.0 37957564 6684 s002 S 3:32PM 0:01.95 /Users/hoge/.wdm/drivers/chromedriver/mac64/106.0.5249/chromedriver --port=50768 hoge 66708 0.0 0.0 37946300 6660 s002 S 2:48PM 0:00.45 /Users/hoge/.wdm/drivers/chromedriver/mac64/106.0.5249/chromedriver --port=55595下面是一个可以使用shell的环境下单行处理的例子,比如Mac或者Linux。
ps=`ps aux | grep 'chromedriver' | grep -v grep | awk '{print $2 }'`;for i in $ps; do kill $i; done参考:在会话结束时退出浏览器
让我们以
quit()结束 Selenium。综上所述
采集时知法。
过去,欺诈性妨碍业务的案件,或网站负载过大的案件,可能会触及刑法“第234条”(损害计算机等妨碍业务)。
此外,如果获取的数据的处理出现问题,则可能会触及版权法。
原创声明:本文系作者授权爱码网发表,未经许可,不得转载;
原文地址:https://www.likecs.com/show-308631907.html