前面的前面
菜鳥一隻蒟蒻一枚輕噴勿嘲 BG
並沒有bg,強行搞一個 正題
亂搞哪來正題一說。
電腦室是7-24開著的,想著用來扒一些東西
然後在我逛p站的時候突然想起來自己三位元的收藏圖片是不是可以抓下來呢。
寫了兩個無作業的晚上, ps:
p站的頻繁異常登入是會反饋給郵箱的,小心郵箱被刷成999+ 登入
這是瀏覽器F12登入時可以看到的,為了不使跳轉後清空我們需要勾上Preserve Log
可以看到這裡除了登陸的帳號密碼還有一個類似驗證的東西postkey
翻網頁原始碼可以看到
<input type="hidden" name="post_key" value="cb02a4460fd7a41fb46d0129e4ca5ece">
訪問pixiv是要一個Referer的(不會翻譯),根據個人理解,它代表的是跳轉前的網址是什麼
這個東西一定要有是蠻重要的不然訪問不到原圖片的 收藏列表
首先是收藏的網址
為了讓爬蟲更像爬蟲,我們要在每個頁面中尋找帶有next類的標籤
<span class="next"><a href="?rest=show&p=2" rel="next" class="_button" title="下一頁">
這樣一個東西,裡面的a就指向下一頁了
如果找不到下一頁,那就是抓到底了 圖片
每一頁的圖片有很多不同解析度的地址,以id為59345668的圖片來說,原圖片在這一行裡面
<img alt="君の名は。" width="780" height="1103" data-src="http://i1.pixiv.net/img-original/img/2016/10/07/01/26/24/59345668_p0.png" class="original-image">
就是這張
於是正則匹配一下就搞出來了,需要注意的是這樣的一條漫畫是沒有的
對於一張圖片有兩種方式儲存 1.
urllib.urlretrieve(url, path, rollFunc)#url是圖片地址,path是本地目錄,那個rollFunc是yy出來的表示下載進度的東西
也就是之前爬百度貼吧用到過的 2.
with open(path, 'wb) as file: file.write(requests.get(url).content)#url同上,path同上,w是寫b是以二進位方式
這裡只用了第二種方法因為快啊 多線程
怎麼樣是不是很高大上對不對很興奮對不對
對於數量級的任務顯然我們是可以讓他們平行處理的,速度提升很顯然
為了方便我直接跳過了Thread因為threading更好用
看代碼
def cal(a, b): print a + bjobs = []for p in xrange(50): jobs.append(threading.Thread(target = cal, args = (1, 2)))for job in jobs: job.start()for job in jobs: job.join()
這裡先定義了一個list用來記錄所有的線程,然後是封裝
target是需要調用的函數(顯然)args是調用參數(還是顯然),args必須是一個tuple
start()和join()分別是開始和等待,保證所有的都線程結束
那麼最終的大概流程就有了
登入1->找到收藏頁的圖片並把下載任務裝進線程->跑一遍->找下一頁的超連結->回到1 字串
過去寫pascal、c++都是直接stra = strb + strc,後面到了python這樣就效率及其低下了
究其原因,在python中string是不可變的,那麼每一次的+運算都要重新開產生個string
又是查網頁,找到解決方案
stra = ''.join(strb, strc)
Code
頭一次寫著麼長的東西,寫寫停停用了幾個晚上。還是很有成就感的 (即使代碼很醜)
import threadingimport requestsimport osimport redef getPage(html, url, headers): while 1: try: page = html.get(url, headers = headers, timeout = 3).content break except Exception, e: print e pass return pagedef logIn(html, url, headers, data): while 1: try: html.post(url, headers = headers, data = data, timeout = 2) return except Exception, e: print e passdef get(html, url, headers, index, filepath): headers['Referer'] = url page = '' while 1: try: page = html.get(url, headers = headers, timeout = 3).content break except Exception, e: print e pass reg = re.compile(r'<img alt=".+?" width="\d+" height="\d+" data-src="(.+?)"') picUrl = re.findall(reg, page) if len(picUrl) == 0: return picUrl = picUrl[0] print picUrl if os.path.exists(r'%s%s%s' %(filepath, str(index), picUrl[-4:])): return headers['Referer'] = picUrl while 1: try: page = html.get(picUrl, headers = headers, timeout = 3).content break except Exception, e: pass with open(r'%s%s%s' %(filepath, str(index), picUrl[-4:]), 'wb') as file: file.write(page) print index print r'%s%s%s' %(filepath, str(index), picUrl[-4:])html = requests.Session()preUrl = 'http://www.pixiv.net/member_illust.php?mode=medium&illust_id='logInUrl = 'https://accounts.pixiv.net/login?return_to=0&lang=zh&source=pc&view_type=page'prefavUrl = 'http://www.pixiv.net/bookmark.php'headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.22 Safari/537.36 SE 2.X MetaSr 1.0'}data = {'return_to': 'http://www.pixiv.net/'}pixivId = raw_input('pixiv id:')password = raw_input('password:')filepath = raw_input('filepath:')data['pixiv_id'] = pixivIddata['password'] = passwordheaders['Referer'] = logInUrllogInPage = getPage(html, logInUrl, headers)reg = re.compile(r'<input type="hidden" name="post_key" value="(.+?)">')postKey = re.findall(reg, logInPage)[0]data['post_key'] = postKeylogIn(html, logInUrl, headers, data)favUrl = prefavUrlindex = 0while 1: headers['Referer'] = favUrl favPage = getPage(html, favUrl, headers) reg = re.compile(r'"data-type="illust"data-id="(\d+)"data-tags=') lis = re.findall(reg, favPage) jobs = [] for p in lis: url = ''.join([preUrl, p]) index += 1 jobs.append(threading.Thread(target = get, args = (html, url, headers, index, filepath))) for job in jobs: job.start() for job in jobs: job.join() reg = re.compile(r'class="next"><a href="(.+?)"') bacUrl = re.findall(reg, favPage) if bacUrl: p = re.sub('&', '&', bacUrl[0]) favUrl = prefavUrl + p print favUrl else: break