爬虫(四)Selenium + Headless Chrome爬取Bing图片搜索结果

Bing图片搜索结果是动态加载的,如果我们直接用requests去访问页面爬取数据,那我们只能拿到很少的图片。所以我们使用Selenium + Headless Chrome来爬取搜索结果。在开始前,需要介绍一下xpath。

XPath

XPath即为XML路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言。使用它让我们可以很方便地定位页面中的各种元素。详细使用方法可以看这里

实例

from selenium import webdriver
from selenium.webdriver.common.by import By
import json
import re
import requests
import os

chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument("--headless")
chrome_options.add_argument("--disable-gpu")
driver = webdriver.Chrome(options=chrome_options)
word = '深秋壁纸'
url = 'https://cn.bing.com/images/search?q={}'.format(word)
save_folder = 'imgs'
if not os.path.exists(save_folder):
    os.makedirs(save_folder)

driver.get(url)
# 获取一行图片
rows = driver.find_elements_by_class_name("dgControl_list")
t = 0
# 只点击一次“更多图片”
mark = True
while mark or t != len(rows):
    if t == len(rows):
        # 找到class为“mm_seemore”的div下的第一个a标签
        element = driver.find_element_by_xpath("//div[@class='mm_seemore']/a[1]")
        # 用JS模拟点击
        driver.execute_script("arguments[0].click()", element)
        mark = False
    # 翻到页面底部
    driver.execute_script('window.scrollTo(0, document.body.scrollHeight)')
    driver.implicitly_wait(0.5)
    t = len(rows)
    rows = driver.find_elements_by_class_name("dgControl_list")
    print(t)

img_url_list = []
for row in rows:
    # 找到图片所在的a标签
    a_list = row.find_elements(By.XPATH, "li/div/div/a")
    for tag in a_list:
        # 获取图片链接
        img_url_list.append(json.loads(tag.get_attribute('m'))['murl'])
driver.quit()
for i in range(len(img_url_list)):
    try:
        img = requests.get(img_url_list[i], timeout=10).content
        # 获取图片格式
        img_format = re.search(r'\.\w+$', img_url_list[i])[0]
    except Exception as e:
        print(e)
        continue
    with open('{}/{}{}.{}'.format(save_folder, word, i, img_format[1:]), 'wb') as f:
        print('{}{}.{}'.format(word, i, img_format[1:]))
        f.write(img)

除了爬取动态页面,我们也完全可以用Selenium + Headless Chrome爬取其他页面。但是因为需要模拟浏览器,加载页面的各种文件,这种方法开销极大。所以如果不是必要,一般都使用开销更小的requests,毕竟绝大多数时候使用requests就能获取到我们想要的数据。另外,用单线程一张张获取图片很慢,如果有兴趣可以自己改成多线程来运行。

posted @ 2019-09-26 19:55  rain_poi  阅读(924)  评论(0编辑  收藏  举报