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()