1. 程式人生 > >[python爬蟲小實戰2]根據使用者輸入關鍵詞爬取今日頭條圖集,並批量下載圖片

[python爬蟲小實戰2]根據使用者輸入關鍵詞爬取今日頭條圖集,並批量下載圖片

這算是比較貼近於實際生活的爬蟲了,根據使用者輸入的關鍵字批量下載今日頭條相關圖集圖片,,核心用到了urllib.request.urlretrieve()這個方法,然後百度了一下進度條怎麼玩,直接把程式碼加上去了,沒毛病,感覺程式碼有些複雜,其實理論上一層網頁可以將所需額圖片都爬取下來,但是當時擔心出現問題,就多添加了一層網頁url分析,主要用的還是json分析,這些都相對簡單的,關鍵一層一層網頁間的url連結分析,當時寫的時候聽懵逼的,迴圈太多(其實寫完後再去看看還是一臉懵逼,懷疑是不是自己寫的),
此次下載的是fate相關的圖片,因為是ajax非同步載入,這個其實很好控制的,但是網頁數量太多,加上有等待時間,就沒有載入太多網頁直接上程式碼吧,(感覺註釋挺明瞭的)

import requests
from bs4 import BeautifulSoup
from skimage import io
import urllib
import re
import time
import json
headers = {
    'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36'
    ,'Accept':'application/json, text/javascript'
,'Host':'www.toutiao.com' ,'Connection':'keep-alive' ,'Accept-Encoding':'gzip, deflate' ,'Accept-Language':'zh-CN,zh;q=0.8' ,'Upgrade-Insecure-Requests':'1' ,'Referer':'http://www.toutiao.com/search/' } url = 'http://www.toutiao.com/search_content/?offset={}&format=json&keyword={}&autoload=true&count=20&cur_tab=3'
#urltest = 'http://www.toutiao.com/search_content/?offset=0&format=json&keyword=fate&autoload=true&count=20&cur_tab=3' urllist = []#建立個列表用於存放每次非同步載入所更新出來的20條網頁url name = input('請輸入所要查詢的圖片關鍵詞') for i in range(0,2):#爬取前100條連結 urllist.append(url.format(i,name)) path = '/Users/loukun/Desktop/picture' def Schedule(a,b,c):#顯示下載進度 ''''' a:已經下載的資料塊 b:資料塊的大小 c:遠端檔案的大小 ''' per = 100.0 * a * b / c if per > 100 : per = 100 sys.stdout.write('\r%.2f%%' % per) time.sleep(1) if per == 100: print('該圖片載入完成') urlname = []#存放每個圖集的名稱 urllist2 = []#存放每個圖集的連結 def get_link(url): session = requests.Session() res = session.get(url) soup = BeautifulSoup(res.text,'html.parser') jd = json.loads(soup.text) for articleurl in jd['data']: name = articleurl['title'] urlimg = articleurl['url'] urlname.append(name) urllist2.append(urlimg) #print('圖集名稱:\n',name,'\n圖集連結:\n',url) return urllist2 #print(urllist) for url in urllist: #print('父URL',url) get_link(url) time.sleep(1) def img_save(urllist3,urlname): i2 = 1 for imgurl,imgname in zip(urllist3,urlname):#將列表中所存放的圖片url打印出來,通過skimage將圖片列印到控制檯上 print('圖片',i2,'連結:',imgurl) print('圖片',i2,'預覽:\n') imgname2 = imgname.lstrip('origin/') try:#檢視圖片 fateimg = io.imread(imgurl) io.imshow(fateimg) io.show() except OSError: print('圖片開啟失敗!!') try:#儲存圖片 if not os.path.exists(path):#若該路徑下面的資料夾不存在則建立一個 os.mkdir(path) urllib.request.urlretrieve(imgurl,path +'/'+ 'fate系列' + imgname2 + '%s.jpg' % i2,Schedule) print('下載完成\n\n') except Exception: print('下載失敗') #time.sleep(1) i2 += 1 #通過正則表示式以及json將每張圖片的url爬取出來並列印並下載到本地資料夾 def get_jsonurl(url,urlnamecon): urllist3 = []#該列表用於存放每張圖片的url urlname = [] res = session.get(url,headers = headers) res.text soup = BeautifulSoup(res.text,'html.parser') message = re.findall('gallery: (.*?),\n',soup.text,re.S)#通過正則表示式將json檔案提取出來 jd = json.loads(message[0])#通過loads方法將json檔案轉化為字典形式 url = jd['sub_images']#通過json線上解析器將解析出來的字典型別的網頁元素通過鍵找出其所對應的值 for url1 in url: urllist3.append(url1['url']) urlname.append(url1['uri'])#將每張圖片的名稱儲存到列表中 img_save(urllist3,urlname) num = 1 for urlcontent,urlnamecon in zip(urllist2,urlname): print('圖集',num,'名稱:',urlnamecon)#列印每個圖集的名稱 print('圖集',num,'連結:',urlcontent)#列印每個圖集的連結 print(len(urlname)) get_jsonurl(urlcontent,urlnamecon) num += 1

執行效果
下載結果
當時檔名沒控制好,一直覆蓋原來的檔案,搞了好長時間,最後還是用了原圖片地址內的部分字串作為檔名了,這樣免的覆蓋了,
總之,馬馬虎虎,還有很多要改進的地方,,歡迎大佬們測試(此程式碼真的挺實用的 #滑稽)