嘿,大伙~ 学了四期Python爬虫的基础内容,我们已经能够在一定程度上独当一面了,所以今天这一期我们就开始实战一下吧!~
对前面三章的补充
前面三期里,我们讲了我们会用到的三个页面解析的方法。
那么问题来了——
什么时候需要用到我们的页面解析的方法呢?
我们打开页面源代码,然后在里面搜索,如果能搜到,那就能用页面解析,不论是Bs4还是Xpath亦或是正则,都是可以的。
这一期里,我们通过爬取三个网站的图片,来简单接触一下怎么爬取网页中的图片,以及怎么存储到本地。
首先第一个网页我们来一点点尝试吧~
图怪兽
下一个,下一个。
上面的步骤我们就不多说了,我们这里就直接展示结果。
访问页面
import requests
headers = {
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
url = 'https://818ps.com/muban/all&0_0_0_0&k_kaigongdaji?top_id=5881371'
html = requests.get(url, headers=headers).text
页面解析
div.searchTemplate_flow_wrap__dGnCV div.searchTemplate_column__Ves_p div.searchTemplate_cart_wrap__1yDpm div.searchTemplate_scroll-wrap__KeGk5 div img
import requests
from bs4 import BeautifulSoup
headers = {
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
url = 'https://818ps.com/muban/all&0_0_0_0&k_kaigongdaji?top_id=5881371'
html = requests.get(url, headers=headers).text
soup = BeautifulSoup(html, 'lxml')
imgs = soup.select('div.searchTemplate_flow_wrap__dGnCV div.searchTemplate_column__Ves_p div.searchTemplate_cart_wrap__1yDpm div.searchTemplate_scroll-wrap__KeGk5 div img')
for img in imgs:
img_alt = img.get('alt')
img_src = img.get('src')
print(img_alt)
print(img_src)
文件存储
import requests
import os
from bs4 import BeautifulSoup
headers = {
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
if not os.path.exists('./818ps'):
os.mkdir('./818ps')
url = 'https://818ps.com/muban/all&0_0_0_0&k_kaigongdaji?top_id=5881371'
html = requests.get(url, headers=headers).text
soup = BeautifulSoup(html, 'lxml')
imgs = soup.select('div.searchTemplate_flow_wrap__dGnCV div.searchTemplate_column__Ves_p div.searchTemplate_cart_wrap__1yDpm div.searchTemplate_scroll-wrap__KeGk5 div img')
for img in imgs:
img_alt = img.get('alt')
img_src = img.get('src')
print('正在下载:', img_alt)
with open('./818ps/{}.jpg'.format(img_alt), 'wb') as f:
f.write(requests.get(img_src, headers=headers).content)
print('下载完成', img_alt)
到这里,我们就写成了和上面的一样,但是我们会发现它报错了。
我们看看上面的img_src。
我们会发现,它少了前面http那一些,虽然我们直接打开这个网址是能打开的,但是从这里,我们是不行的,所以我们要加上前缀。
还有这个是我们前面的Bs4的语句写的不完善,但是在那边不是很好改,我们就直接在代码里面加一个判断就好。
代码
import requests
import os
from bs4 import BeautifulSoup
headers = {
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
if not os.path.exists('./818ps'):
os.mkdir('./818ps')
url = 'https://818ps.com/muban/all&0_0_0_0&k_kaigongdaji?top_id=5881371'
html = requests.get(url, headers=headers).text
soup = BeautifulSoup(html, 'lxml')
imgs = soup.select('div.searchTemplate_flow_wrap__dGnCV div.searchTemplate_column__Ves_p div.searchTemplate_cart_wrap__1yDpm div.searchTemplate_scroll-wrap__KeGk5 div img')
for img in imgs:
img_alt = img.get('alt')
img_src = 'https:' + img.get('src')
if img_alt:
print('正在下载:', img_alt)
with open('./818ps/{}.jpg'.format(img_alt), 'wb') as f:
f.write(requests.get(img_src, headers=headers).content)
print('下载完成', img_alt)
效果就是这样,
这个如果想要继续下载,也能够翻页,和上面的操作基本是一样的,这里就不赘述了。
百度图片
下面是我们今天的最后一个网页图片了,百度还是有牌面的,压轴了也是。
差异
这个和前面两个有一个本质上的区别:它是一个 ajax 动态加载,也叫做瀑布流。
什么意思呢?
大家很容易就能观察到,在我们页面中,随着我下翻页面,它的内容是一点点更新出来。
那么对于这种我们要怎么去获取,这种的存储都通过json文件来进行存储的。
所以我们只需要抓到存储图片内容的json文件的包就行了。
抓 json 包
我们进到检查的网络板块,然后不断下翻我们的百度图片的页面,然后筛选一下
Fetch/XHR
我们会看到这些就是我想要的存储内容了。
但是它存储之中有很多个都是,那么我们怎么把所有都给弄下来呢??
大伙,观察一下我们会发现它的 url 里唯一改变的就只有 pn 和 curPageNum,很好理解,这就是翻页了。
所以,我们只需要写一个循环来遍历一下这个载荷就可以了。
那么,我们动手吧!~
代码
这次的代码,我们尝试一下前面 params 传递的方式。
params 也就是载荷里的内容。
如果,我们直接复制它的url,我们会发现我们爬不下来东西,因为其中搜索的部分被它转换成了对应编码,如果要用这种方式,我们要把编码换回中文。
"""
ajax 动态加载 瀑布流
------>>> 寻找json文件。
"""
import requests
url = 'https://image.baidu.com/search/albumsdata?'
params = {
'pn': '90',
'rn': '30',
'tn': 'albumsdetail',
'word': '城市建筑摄影专题',
'album_tab': '建筑',
'album_id': '7',
'ic': '0',
'curPageNum': '3'
}
headers = {
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36'
}
html = requests.get(url, params=params)
print(html.json())
到这里,我们就把其中一个 json包 爬下来了。
那么下一步,就是进行存储,这里的操作和前面是一样的。
文件存储
来看看我是怎么做的吧~
代码
"""
ajax 动态加载 瀑布流
------>>> 寻找json文件。
"""
import requests
import os
if not os.path.exists('./baidu'):
os.mkdir('./baidu')
url = 'https://image.baidu.com/search/albumsdata?'
params = {
'pn': '90',
'rn': '30',
'tn': 'albumsdetail',
'word': '城市建筑摄影专题',
'album_tab': '建筑',
'album_id': '7',
'ic': '0',
'curPageNum': '3'
}
headers = {
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36'
}
html = requests.get(url, params=params).json()
for res in html['albumdata']['linkData']:
img_pid = res['pid']
img_url = res['thumbnailUrl']
print('正在下载:', img_pid)
with open('./baidu/{}.jpg'.format(img_pid), 'wb') as f:
f.write(requests.get(img_url, headers=headers).content)
print('下载完成', img_pid)
多文件存储
按照前面所说,我们只需要把 pn 和 curPageNum 进行遍历即可。
这个也是和前面说的差不多,大家可以试试,如果不行,那就看看我的写法吧!~
代码
"""
ajax 动态加载 瀑布流
------>>> 寻找json文件。
"""
import requests
import os
if not os.path.exists('./baidu'):
os.mkdir('./baidu')
url = 'https://image.baidu.com/search/albumsdata?'
for i in range(5):
params = {
'pn': str(i * 30),
'rn': '30',
'tn': 'albumsdetail',
'word': '城市建筑摄影专题',
'album_tab': '建筑',
'album_id': '7',
'ic': '0',
'curPageNum': str(i)
}
headers = {
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36'
}
html = requests.get(url, params=params).json()
for res in html['albumdata']['linkData']:
img_pid = res['pid']
img_url = res['thumbnailUrl']
print('正在下载:', img_pid)
with open('./baidu/{}.jpg'.format(img_pid), 'wb') as f:
f.write(requests.get(img_url, headers=headers).content)
print('下载完成', img_pid)
效果
写完上面这个,我发现我们日常所使用到的百度图片不长这个样子。
所以,下面重新写一个。
新·百度图片
在我们从百度图片里找图片,遇到更多的都是这个样子的,所以这里重新写一个,大差没有,小差别还是有一些,所以就简单过一下。
抓json包
这里我们演示一下怎么直接改url。
import requests
'https://image.baidu.com/search/acjson?tn=resultjson_com&logid=12238656010602840941&ipn=rj&ct=201326592&is=&fp=result&fr=&word=%E5%A3%81%E7%BA%B8&cg=wallpaper&queryWord=%E5%A3%81%E7%BA%B8&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&hd=&latest=©right=&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&expermode=&nojc=&isAsync=&pn=120&rn=30&gsm=78&1739954761925='
url = 'https://image.baidu.com/search/acjson?tn=resultjson_com&logid=12238656010602840941&ipn=rj&ct=201326592&is=&fp=result&fr=&word=壁纸&cg=wallpaper&queryWord=壁纸&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&hd=&latest=©right=&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&expermode=&nojc=&isAsync=&pn=120&rn=30&gsm=78&1739954761925='
headers = {
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36'
}
html = requests.get(url, headers=headers)
print(html.json())
文件存储
import requests
import os
if not os.path.exists('./baidu'):
os.mkdir('./baidu')
url = 'https://image.baidu.com/search/acjson?tn=resultjson_com&logid=12238656010602840941&ipn=rj&ct=201326592&is=&fp=result&fr=&word=壁纸&cg=wallpaper&queryWord=壁纸&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&hd=&latest=©right=&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&expermode=&nojc=&isAsync=&pn=120&rn=30&gsm=78&1739954761925='
headers = {
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36'
}
html = requests.get(url, headers=headers).json()
for res in html['data']:
if res: # 最后一个是空的,需要把它排除掉
img_title = res['fromPageTitle']
img_title = img_title.replace('|', '_').strip()
img_url = res['hoverURL']
if img_url: # 有一些没有提供 url,也需要排除掉
print('正在下载:', img_title)
with open('./baidu/{}.jpg'.format(img_title), 'wb') as f:
f.write(requests.get(img_url, headers=headers).content)
print('下载完成', img_title)
多文件存储
import requests
import os
if not os.path.exists('./baidu'):
os.mkdir('./baidu')
'https://image.baidu.com/search/acjson?tn=resultjson_com&logid=12238656010602840941&ipn=rj&ct=201326592&is=&fp=result&fr=&word=%E5%A3%81%E7%BA%B8&cg=wallpaper&queryWord=%E5%A3%81%E7%BA%B8&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&hd=&latest=©right=&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&expermode=&nojc=&isAsync=&pn=120&rn=30&gsm=78&1739954761925='
for i in range(1, 3): # pn为0的时候无法访问
url = f'https://image.baidu.com/search/acjson?tn=resultjson_com&logid=12238656010602840941&ipn=rj&ct=201326592&is=&fp=result&fr=&word=壁纸&cg=wallpaper&queryWord=壁纸&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&hd=&latest=©right=&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&expermode=&nojc=&isAsync=&pn={str(i * 30)}&rn=30&gsm=78&1739954761925='
print(url)
headers = {
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36'
}
html = requests.get(url, headers=headers).json()
for res in html['data']:
if res: # 最后一个是空的,需要把它排除掉
img_title = res['fromPageTitle']
img_title = img_title.replace('|', '_')
img_title = img_title.replace(':', '_').strip()
img_url = res['hoverURL']
if img_url: # 有一些没有提供 url,也需要排除掉
print('正在下载:', img_title)
with open('./baidu/{}.jpg'.format(img_title), 'wb') as f:
f.write(requests.get(img_url, headers=headers).content)
print('下载完成', img_title)
总结
OKk,本期的内容就到这里了,爬取网页图片,按照我们前面所获取的知识已经够了,大家多多练习,就可以轻松拿到喜欢的图片了。