B站壁纸爬虫
- exe下载:链接 提取码:7ic2
- 相关代码:见博文
- 说明:网络爬虫“盗亦有道“,查看b站的robots协议可以发现部分是不允许商业/恶意爬取的,所以图片的版权归作者,任何利用资料的盈利行为将可能触及法律边界
-
技术线:requests - bs4
-
实现思路:由用户输入关键字,然后在搜索框模拟输入“关键字 + 壁纸”并进去“专栏”网页。依次进入每个链接里爬取图片,并爬完当前页进入下一页
-
具体流程:
-
进入“专栏“
-
我先搜索了蕾姆和御坂美琴两个关键字,可以发现规律就是keyword=xxx
-
那么获得用户输入后就可以造出相应的专栏的网站url
-
代码大概这样写:
keyword = input(\'输入你想爬取的角色名:\') + \'壁纸\' url = \'https://search.bilibili.com/article?keyword=\' + keyword -
有一个小问题,这样只能跳转到第1页,如果想爬取第二页怎么办呢?
-
很容易发现规律,网站的url变化只是在page那发生了改动
-
所以不妨可以写出造出爬取n页的代码:
keyword = input(\'输入你想爬取的角色名:\') + \'壁纸\' dep = int(input(\'输入爬取的深度(页数):\')) for i in range(0, dep): url = \'https://search.bilibili.com/article?keyword=\' + keyword + \'&page=\' + str(i + 1) -
OK这样就爬取到了n页“专栏”的url。
-
-
进入相应的链接
-
可以看到,我们必须进入每一个链接才能爬取图片,所以我查看了“专栏”网页的源代码,如下
-
可以看到,每个链接都是在一个< li >标签里,并且其属性的class为article-item(我用高亮标识出来了)
-
那么就可以用bs4的find_all就可以找到每一个标签,代码如下:
lis = soup.find_all(\'li\', attrs={\'class\', \'article-item\'}) -
但是具体的链接通过源代码可以发现是在< li >标签下的< a >标签里的href属性,所以找出链接的代码如下:
for li in lis: a = li.find(\'a\') url = \'https:\' + a.attrs[\'href\']
-
-
爬取图片
-
进入每一个链接后效果如上,但如何爬取下每一张图片呢,我再一次查看源代码
-
发现属性class为article-holder的div标签里存储的是这个链接里所有正文部分里图片的url,div儿子中每一个< img >标签里就有一张图片的url链接,我们截取出来即可,代码如下:
div = soup.find(\'div\', attrs={\'class\', \'article-holder\'}) imgs = div.find_all_next(\'img\') for img in imgs: link = \'https:\' + img.attrs[\'data-src\']
-
-
-
效果图
-
程序开头
-
爬取过程
-
成果图
-
-
全部代码:
# 壁纸爬虫
import requests, bs4, os, time
from bs4 import BeautifulSoup
ans = []
def makeSoup(url):
try:
r = requests.get(url)
r.raise_for_status()
return BeautifulSoup(r.text, \'html.parser\')
except:
pass
def getData(url):
try:
soup = makeSoup(url)
div = soup.find(\'div\', attrs={\'class\', \'article-holder\'})
imgs = div.find_all_next(\'img\')
for img in imgs:
link = \'https:\' + img.attrs[\'data-src\']
ans.append(link)
except:
pass
def getHtml(soup):
count = 0
print(\'\r进度:0.00\', end="")
lis = soup.find_all(\'li\', attrs={\'class\', \'article-item\'})
for li in lis:
a = li.find(\'a\')
url = \'https:\' + a.attrs[\'href\']
getData(url)
count += 1
print(\'\r进度:{:.2%}\'.format(count / len(lis)), end="")
def getName(url):
return str(url.split(\'/\')[-1].split(\'.\')[0]) + \'.jpg\'
def download():
count = 0
n = int(input(\'\n已捕获图片\' + str(len(ans)) + \'张,请输入要下载的张数:\'))
if n > len(ans) or n < 0: n = 0
root = \'D:\爬虫文件夹\' + \'\\\'
if not os.path.exists(root): os.mkdir(root)
for i in range(0, n):
path = root + getName(ans[i])
if not os.path.exists(path):
try:
r = requests.get(ans[i])
with open(path, \'wb\') as f:
f.write(r.content)
except:
pass
count += 1
print(\'\r进度:{:.2%}\'.format(count / n), end="")
print(\'下载完成\')
def main():
print(\'0. 开发者:周其星\')
print(\'1. 本程序仅用来学习交流,用于盈利行为后果自负!\')
print(\'2. 爬取的资源将会下载到D盘的\"爬虫资源\"里\')
print(\'3. 有些图片分辨率过高可以通过\"画图\"打开\')
print(\'4. 网络不行可能会导致跳过下载某些资源,重新试几次就行\')
print()
keyword = input(\'输入你想爬取的角色名:\') + \'壁纸\'
dep = int(input(\'输入爬取的深度(页数):\'))
for i in range(0, dep):
url = \'https://search.bilibili.com/article?keyword=\' + keyword + \'&page=\' + str(i + 1)
getHtml(makeSoup(url))
download()
time.sleep(2)
if __name__ == \'__main__\': main()