“静态网页"和"动态网页”
"静态网页":一次性加载,爬虫可以爬到全部信息。关于静态网页的Demo
“动态网页”:分多次加载,爬虫只能爬取部分信息(无法直接执行JavaScript代码带来的问题)。
接下来让我们用selenium开始解析动态网页吧
我们需要的工具selenium
selenium是什么?有啥用?我们用了它能解决什么问题?
selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题。
selenium本质是通过驱动浏览器,完全模拟浏览器的操作,比如跳转、输入、点击、下拉等,来拿到网页渲染之后的结果,可支持多种浏览器。
selenium的下载和安装
提供两种方法
1、pip xxx
2、打开pycharm等软件,自行搜索库名下载。
selenium对应浏览器插件的下载和安装
下方是selenium支持的浏览器
Chrome
Firefox
PhantomJS
Safari
Edge
根据自己的浏览器类别去下载对应的浏览器插件,接下来用Chrome做例子。
1、查看自己浏览器的版本
打开浏览器,在地址栏输入chrome://version/
2.下载对应的插件
Chrome插件下载地址
找到和自己浏览器版本最接近的版本,点击进去,点击对应操作系统的链接进行下载。
Hello Word~(测试环境是否成功)
from selenium import webdriver
driver = webdriver.Chrome ('你下载的浏览器插件的路径')
如果弹出Chrome窗口,恭喜你。
如果报错,请你检查一下上面步骤或者百度
壁纸网址介绍
超级好看的的壁纸网站
简单说一下这个网站的特点
1、下拉式加载壁纸
2、JS加载壁纸
3、每个壁纸都有很多版本(4K、2K等)
源码
import os
import random
import ssl
import time
ssl._create_default_https_context = ssl._create_unverified_context
from bs4 import BeautifulSoup
import urllib.request
'''
在这说明一下 为什么要用selenium
1、有些页面是异步加载返回的,它不是直接返回请求的数据,爬虫只能抓取到最开始的部分数据(空壳数据)后面的数据是由Javascript异步加载进来的
2、爬虫不能解决js加载的问题,所以我们要用selenium
3、我们需要利用selenium抓取js加载的数据(壁纸)
'''
from selenium import webdriver # 调用浏览器做操作
from selenium.webdriver.common.by import By # 按照什么方式查找,By.ID,By.CSS_SELECTOR
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait # 等待页面加载某些元素 js加载
# 指定Chrome驱动的位置
chromePath = '/Users/apple/Downloads/Chrome下载/chromedriver'
# 壁纸保存的路径
savePath = '/Users/apple/Downloads/desktopPictureTest'
# 下该函数为载壁纸 pageCode参数:选择壁纸的种类 maxSlideNumber参数:下拉的次数
def downloadPicture(pageCode, maxSlideNumber):
# 打开Chrome浏览器
browser = webdriver.Chrome(chromePath)
print('打开Chrome中...')
# 由于这个网站下拉加载更多的壁纸 所以 初始化下拉次数
slideNumber = 1
# 存放爬取到的图片href
DownloadList = []
# 下载失败的图片href
noDownloadList = []
try:
# 跳转到壁纸页面
browser.get('https://ss.netnr.com/wallpaper' + pageCode)
# 我们需要的壁纸放在class名为'row'的div中 我们需要等这个div加载好 我们再抓数据
while True:
try:
# 有时候服务器和网会有点小问题,所以给row10秒加载 如果加载大于10秒 刷新网页 重新开始
wait = WebDriverWait(browser, 10)
# 等到CLASS_NAME为raw的div加载完毕,最多等10秒
wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'row')))
# 如果达到了下拉次数,则跳出循环
if slideNumber > maxSlideNumber:
break
# 没达到下拉次数 +1继续循环
slideNumber = slideNumber + 1
# 如果div加载成功我们需要更多的壁纸,所以下滑到底。
print('下拉中....')
browser.execute_script('window.scrollTo(0,document.body.scrollHeight)')
# 睡眠5秒再次下拉 可以充分展现下拉的用处
time.sleep(5)
# 如果加载大于10秒 刷新网页 重新开始
except:
# 刷新网页
print('刷新网页...')
browser.refresh()
# 此时的网页就是下拉n次后的网页 蕴含着好多壁纸
# 处理网页内容
soup = BeautifulSoup(browser.page_source, "html.parser")
# 抓取div
rows = soup.findAll(class_='list-group')
for i in rows:
# 抓取a标签
aHref = i.findAll('a')
for i in aHref:
# 抓取href(下载地址)
src = i.get('href')
# 把壁纸的href放入列表
DownloadList.append(src)
# 为什么要break呢 因为此网站提供好几个版本的壁纸 我们只需要第一个(画质最好的版本)
break
# 此时开始下载壁纸
# 如果文件夹不存在则创建
if not os.path.exists(savePath):
os.makedirs(savePath)
# 所有的图片处理完成(失败或者成功) 才可以结束
# 可能因为网络和机器的问题,下载会失败,所以采用循环机制
print('\033[0;36m')
print('共抓取到' + str(DownloadList.__len__()) + '张壁纸')
print('\033[0m')
print(
'<=====================================================================================================================================>')
# 无论处理成功还是失败,列表的数据处理完才能结束
while DownloadList.__len__()>0:
# 遍历列表 逐个下载壁纸
for i in DownloadList:
# 壁纸名称
name = i.split('/')[-1]
# 避免名称重复 采用随机数
saveFile = savePath + "/" + 'qianFuXin' + str(random.randint(0, 9)) + str(random.randint(0, 9)) + \
str(random.randint(0, 9)) + str(random.randint(0, 9)) + name
if os.path.exists(saveFile):
print(saveFile + '已经存在')
exit(0)
try:
urllib.request.urlretrieve(i, saveFile)
# 下载成功就移除列表
DownloadList.remove(i)
print('处理成功!该文件为:' + saveFile)
print('还剩' + str(DownloadList.__len__()) + '张')
print(
'<=====================================================================================================================================>')
except:
# 下载失败就等下次继续下载
noDownloadList.append(i)
print("\033[37;41m处理失败\033[0m")
DownloadList.remove(i)
print('还剩' + str(DownloadList.__len__()) + '张')
print(
'<=====================================================================================================================================>')
# 输出未完成的href 人工处理
print("\033[37;41m未完成的图片href如下\033[0m")
for i in noDownloadList:
print(i)
finally:
# 关闭Chrome页面
browser.close()
def initChoose():
pictureKindAndCode = {'最新壁纸': '#', '4K专区': '#36', '美女模特': '#6',
'爱情美图': '#30', '风景大片': '#9',
'小清新': '#15', '动漫卡通': '#26',
'明星风尚': '#11', '萌宠动物': '#14',
'游戏壁纸': '#5', '汽车天下': '#12',
'炫酷时尚': '#10', '日历壁纸': '#29',
'影视剧照': '#7', '节日美图': '#13',
'军事天地': '#22', '劲爆体育': '#16',
'baby秀': '#18', '文字控': '#35'}
pictureKindAndNumber = {}
number = 1
print(
'<=====================================================================================================================================>')
for i in pictureKindAndCode:
print(str(number) + '、' + i)
pictureKindAndNumber[str(number)] = i
number = number + 1
print(
'<=====================================================================================================================================>')
userChoose = input("\033[1;30;47m输入壁纸编号(范围:1-19):\033[0m")
# 正则表达式判断输入是不是在数字范围内
# matches 只要有一个满足就行 11 是满足[1-9]的 因为1满足了[1-9]
# 做个标记
# 改用isdigit
if userChoose.isdigit() and 20 > int(userChoose) > 0:
pageCode = pictureKindAndCode[pictureKindAndNumber[userChoose]]
else:
print("\033[37;41m请输入1-19之间的数字\033[0m")
exit(0)
maxSlideNumber = input("\033[1;30;47m输入下拉次数(范围1-99):\033[0m")
# 正则表达式判断输入是不是在数字范围内
# matches 只要有一个满足就行
if userChoose.isdigit() and 100 > int(userChoose) > 0:
pass
else:
print("\033[37;41m请输入1-99之间的数字\033[0m")
exit(0)
return pageCode, maxSlideNumber
if __name__ == '__main__':
print('\033[0;36m')
print('Default ChromePath\t==>\t' + chromePath)
print('Default SavePicturePath\t==>\t' + savePath)
print('\033[0m')
# 确定路径是都正确
defaultPathChoose = input('请查看上方路径是否正确,如果正确输入1继续执行程序,否则输入任意字符退出程序:')
if defaultPathChoose.__eq__('1'):
pass
else:
exit(0)
# 初始化选择
pageCode, maxSlideNumber = initChoose()
print('准备下载壁纸.....')
# 下载壁纸
downloadPicture(pageCode, int(maxSlideNumber))
#结束下载
print('\033[0;36m')
print('下载结束')
print('\033[0m')