首页 > 解决方案 > 通过属性获取元素并使用驱动程序单击 webscraping 中的子元素 - Python

问题描述

来自 Indeed.com 的网页抓取结果

- 在“加利福尼亚州洛杉矶”中搜索“Junior Python”(完成)

- 有时会打开弹出窗口。如果出现弹出窗口,请关闭窗口。(完成)

- 前 3 名的结果是赞助的,所以跳过这些并进入真正的结果

- 单击结果摘要部分,打开带有完整摘要的侧面板

- 抓取完整的摘要

- 单击结果摘要时,URL 会发生变化。而不是打开新窗口,我想刮掉侧面板的完整摘要

- 每个真实结果都在('div':{'data-tn-component':'organicJob'}). 我可以使用 BeautifulSoup 获得职位、公司和简短摘要。但是,我想在侧面板上获得完整的摘要。

问题

1)当我尝试点击链接(使用 Selenium)(职位或简短摘要,打开侧面板)时,代码只会点击第一个链接,即“赞助”。无法在 id='jobOrganic' 下找到并点击真实结果

2)一旦(手动)单击实际结果,我可以看到完整的摘要侧面板位于下方<td id='auxCol'>,在此下方。完整的摘要包含在<p>标签中。当我尝试使用 selenium 抓取完整摘要findAll('div':{'id':'vjs-desc'})时,我得到的只是空白结果 []。

3) 打开侧面板时,url 也会发生变化。我尝试使用 Selenium 让驱动程序获取新的 url,然后通过 url 获取结果,但我得到的只是第一个赞助结果,这不是我想要的。我不确定为什么 BeautifulSoup 不断获得赞助的结果,即使我在'id='jobOrganic'真实结果下运行代码也是如此。

这是我的代码。在过去的两天里,我一直在研究这个问题,浏览了 stackoverflow、文档和谷歌,但找不到答案。我希望有人能指出我做错了什么以及为什么我无法获得完整的摘要。

感谢和抱歉这么久。

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from bs4 import BeautifulSoup as bs    

url = 'https://www.indeed.com/'
driver = webdriver.Chrome()
driver.get(url)

whatinput = driver.find_element_by_id('text-input-what')
whatinput.send_keys('Junior Python')

whereinput = driver.find_element_by_id('text-input-where')
whereinput.click()
whereinput.clear()
whereinput.send_keys('Los Angeles, CA')

findbutton = driver.find_element_by_xpath('//*[@id="whatWhere"]/form/div[3]/button')
findbutton.click()

try:
    popup = driver.find_element_by_id('prime-popover-close-button')
    popup.click()
except:
    pass

这就是我卡住的地方。结果摘要在 {'data-tn-component':'organicJob'}, span class='summary' 下。单击此按钮后,将打开侧面板。

soup = bs(driver.page_source,'html.parser')
contents = soup.findAll('div',{"data-tn-component":"organicJob"})
for each in contents:
    summary = driver.find_element_by_class_name('summary')
    summary.click()

这会打开侧面板,但它会单击整个页面中的第一个赞助链接(赞助链接),而不是真正的结果。由于某种原因,这基本上超出了“organicJob”结果集。

url = driver.current_url
driver.get(url)

单击链接(赞助)后,我尝试设置新网址以测试我是否甚至可以获得侧面板的完整摘要(尽管是赞助的,作为测试目的)。

soup=bs(driver.page_source,'html.parser')
fullsum = soup.findAll('div',{"id":"vjs-desc"})
print(fullsum)

这实际上会打印出侧面板的完整摘要,但它会在整个循环中一遍又一遍地打印相同的第一个结果,而不是移动到下一个结果。

标签: pythonseleniumselenium-webdriverweb-scrapingbeautifulsoup

解决方案


问题是您正在div使用漂亮的汤来获取 s,但是单击使用不知道您收集的 div 的 selenium。
当您使用对象find_element_by_class_name()的方法时driver。它搜索整个页面而不是您想要的 div 对象each(在 for 循环中)。因此,它最终在每次迭代中从整个页面中获取相同的第一个结果。
一,仅使用 selenium 可以快速解决问题(但这会更慢)

elements = driver.find_elements_by_tag_name('div')
for element in elements:
    if "organicJob" in element.get_attribute("data-tn-component"):
        summary = element.find_element_by_class_name('summary')
        summary.click()

上面的代码将搜索所有的 div 并遍历它们以找到data-tn-component属性包含organicJob. 一旦找到一个,它将搜索具有类名的元素summary并单击该元素。


推荐阅读