[英]Efficient download of images from website with Python and selenium
免责声明:我没有网络抓取/ HTML / javascripts / css之类的背景,但是我知道一些Python。
我的最终目标是使用相关标签在ShapeNet网站中下载每3515个汽车视图的所有第4个图像视图。 例如,3515对中的第一对是可以在该图片右侧的折叠菜单中找到的图片:(可以通过单击第一页的第一项,然后单击图片来加载)
带有相关标签“ sport utility”的图片,如第一张图片所示(第一辆车的左上方)。
为此,我在@DebanjanB的帮助下编写了一段代码,单击第一张图片上的sport实用程序可打开iframe点击图片,然后将第四个图片链接下载到我的问题 。 完整的工作代码如下:
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time
import os
profile = webdriver.FirefoxProfile()
profile.set_preference("network.proxy.type", 1)
profile.set_preference("network.proxy.socks", "yourproxy")
profile.set_preference("network.proxy.socks_port", yourport)
#browser = webdriver.Firefox(firefox_profile=profile)
browser = webdriver.Firefox()
browser.get('https://www.shapenet.org/taxonomy-viewer')
#Page is long to load
wait = WebDriverWait(browser, 30)
element = wait.until(EC.element_to_be_clickable((By.XPATH, "//*[@id='02958343_anchor']")))
linkElem = browser.find_element_by_xpath("//*[@id='02958343_anchor']")
linkElem.click()
#Page is also long to display iframe
element = wait.until(EC.element_to_be_clickable((By.ID, "model_3dw_bcf0b18a19bce6d91ad107790a9e2d51")))
linkElem = browser.find_element_by_id("model_3dw_bcf0b18a19bce6d91ad107790a9e2d51")
linkElem.click()
#iframe slow to be displayed
wait.until(EC.frame_to_be_available_and_switch_to_it((By.ID, 'viewerIframe')))
#iframe = browser.find_elements_by_id('viewerIframe')
#browser.switch_to_frame(iframe[0])
element = wait.until(EC.element_to_be_clickable((By.XPATH, "/html/body/div[3]/div[3]/h4")))
time.sleep(10)
linkElem = browser.find_element_by_xpath("/html/body/div[3]/div[3]/h4")
linkElem.click()
img = browser.find_element_by_xpath("/html/body/div[3]/div[3]//div[@class='searchResult' and @id='image.3dw.bcf0b18a19bce6d91ad107790a9e2d51.3']/img[@class='enlarge']")
src = img.get_attribute('src')
os.system("wget %s --no-check-certificate"%src)
这有几个问题。 首先,我需要手动了解每个模型的xpath model_3dw_ bcf0b18a19bce6d91ad107790a9e2d51 ,我还需要提取它们都可以在以下位置找到的标签: 。 因此,我需要通过检查显示的每个图像来提取它。 然后,我需要切换页面(有22页),甚至可能在每个页面上向下滚动以确保我拥有所有内容。 其次,我不得不使用time.sleep两次,因为其他基于等待可点击的方法似乎无法按预期工作。
我有两个问题,第一个是显而易见的,这是正确的方法吗? 我觉得即使没有时间也可以很快,睡眠感觉很像人类会做的事情,因此如果确实要走,那么第二效率必须非常低下:我该如何编写double for loop on页面和项目能够有效地提取标签和模型ID?
编辑1:似乎:
l=browser.find_elements_by_xpath("//div[starts-with(@id,'model_3dw')]")
可能是迈向完成的第一步
编辑2:几乎在那里,但是代码充满了time.sleep。 仍然需要获取标签名称并遍历页面
编辑3:获得标记名称仍需要循环浏览页面,并将发布解决方案的初稿
因此,让我尝试正确理解您的意思,然后查看是否可以帮助您解决问题。 我不了解Python,所以请原谅我的synthax错误。
您要单击每辆183533汽车,然后在弹出的iframe中下载第4张图片。 正确?
现在,如果是这种情况,让我们看一下您需要的第一个元素,即页面上装有所有汽车的元素。
因此,要获得第1页的所有160辆汽车,您将需要:
elements = browser.find_elements_by_xpath("//img[@class='resultImg lazy']");
这将为您返回160个图像元素。 确切显示的图像量(第1页)
然后您可以说:
for el in elements:
{here you place the code you need to download the 4th image,
so like switch to iframe, click on the 4th image etc.}
现在,对于第一页,您已经制作了一个循环,该循环将为上面的每辆车下载第4张图像。
由于您有多个页面,因此不能完全解决您的问题。 值得庆幸的是,第一页和/或最后一页的上一页和下一页页面导航均显示为灰色。
所以你可以说:
browser.find_element_by_xpath("//a[@class='next']").click();
只要确保您捕获到元素不可点击的位置即可,因为元素将在最后一页显示为灰色。
与其抓取网站,不如考虑检查网页用来查询数据的URL,然后使用Python的“ requests”包直接从服务器直接发出API请求。 我不是该站点的注册用户,因此无法向您提供任何示例,但是描述shapenet.org网站的论文特别提到:
“为了方便地访问ShapeNet中包含的所有模型和注释数据,我们使用Apache Solr框架在所有3D模型及其相关注释上构建了一个索引。每个给定的3D模型都存储了一个注释包含在索引中作为单独的属性,可以通过简单的基于Web的UI轻松查询和过滤。此外,为了使研究人员可以方便地访问数据集,我们提供了批量下载功能。”
这表明只要您能够了解他们的查询语言所提供的内容,通过API进行所需的操作可能会更容易。 在他们的质量检查/论坛中进行搜索可能也很有用。
我想出了这个答案,这是一种有效的方法,但是我不知道如何删除多个time.sleep睡眠,直到有人发现更优雅的东西(也就是最后一个结尾时)我才会接受我的答案页面失败):
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time
import os
profile = webdriver.FirefoxProfile()
profile.set_preference("network.proxy.type", 1)
profile.set_preference("network.proxy.socks", "yourproxy")
profile.set_preference("network.proxy.socks_port", yourport)
#browser = webdriver.Firefox(firefox_profile=profile)
browser = webdriver.Firefox()
browser.get('https://www.shapenet.org/taxonomy-viewer')
#Page is long to load
wait = WebDriverWait(browser, 30)
element = wait.until(EC.element_to_be_clickable((By.XPATH, "//*[@id='02958343_anchor']")))
linkElem = browser.find_element_by_xpath("//*[@id='02958343_anchor']")
linkElem.click()
tag_names=[]
page_count=0
while True:
if page_count>0:
browser.find_element_by_xpath("//a[@class='next']").click()
time.sleep(2)
wait.until(EC.presence_of_element_located((By.XPATH, "//div[starts-with(@id,'model_3dw')]")))
list_of_items_on_page=browser.find_elements_by_xpath("//div[starts-with(@id,'model_3dw')]")
list_of_ids=[e.get_attribute("id") for e in list_of_items_on_page]
for i,item in enumerate(list_of_items_on_page):
#Page is also long to display iframe
current_id=list_of_ids[i]
element = wait.until(EC.element_to_be_clickable((By.ID, current_id)))
car_image=browser.find_element_by_id(current_id)
original_tag_name=car_image.find_element_by_xpath("./div[@style='text-align: center']").get_attribute("innerHTML")
count=0
tag_name=original_tag_name
while tag_name in tag_names:
tag_name=original_tag_name+"_"+str(count)
count+=1
tag_names.append(tag_name)
car_image.click()
wait.until(EC.frame_to_be_available_and_switch_to_it((By.ID, 'viewerIframe')))
element = wait.until(EC.element_to_be_clickable((By.XPATH, "/html/body/div[3]/div[3]/h4")))
time.sleep(10)
linkElem = browser.find_element_by_xpath("/html/body/div[3]/div[3]/h4")
linkElem.click()
img = browser.find_element_by_xpath("/html/body/div[3]/div[3]//div[@class='searchResult' and @id='image.3dw.%s.3']/img[@class='enlarge']"%current_id.split("_")[2])
src = img.get_attribute('src')
os.system("wget %s --no-check-certificate -O %s.png"%(src,tag_name))
browser.switch_to.default_content()
browser.find_element_by_css_selector(".btn-danger").click()
time.sleep(1)
page_count+=1
也可以从硒中导入NoSuchElementException,并使用try进行while True循环,除了摆脱任意的time.sleep。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.