Scrapy第二篇: 多層次網頁爬取 | 圖片爬取
(先隨便放個封面圖)
看到這個標題,目測一大波老司機心里開始os:難道又是 妹子圖???
(我。。。我還能說什么)
寶寶的品位可不一般的好吧?。?!
這年代最流行什么呀?
當然是“女神”,“?;ā崩玻。。。~,說“網紅”的當我沒說。。)
顏值高,有范兒,關鍵氣質逆天對不對~
比如這樣:
這樣:
或者這樣:
這樣:
</br>
不錯吧?(嘿嘿據說最后這個還是我川的妹子~)心動不如行動,今天我們就用Scrapy把諸位女神收入囊中!
目標網站:唯一圖庫
搜索關鍵詞:?;?br>
一、步驟
1、首先分析網站
打開上面這個頁面
點完之后發現,真的只有6頁。
隨便點擊進入某個主頁
看完第一個圖,來看后面的圖
可以看出規律了吧,皆是是 url=xxx+_n.html(n為1,2,3...)的結構,只要獲得前面那一串和最大頁數就可以構造了。
但是進一步分析就會發現,每個MM個人頁面內圖片的URL結構是不一樣的(這里也要注意),如下所示:
基本上無規律可循,不能構造出來,只能從源碼中獲取圖片真實鏈接
2、思路
用Scrapy爬取思路:
1)先獲取首頁siteURL,以及標題
2)然后由其進入MM個人頁面獲取最大頁數Num和第一個圖片URL
3)構造每一個圖片地址pageURL
4)requests獲取源碼中具體原圖地址detailURL
5)獲取圖片并保存入文件,以1)中標題作為文件名
這里就涉及到了多層次頁面爬取的問題
怎么辦呢,不要忘了,可以用meta傳參數。
二、代碼
首先來看整個項目的文件結構
以為沒有本項目用到middlewares中間件,所以刪去了
entrypoint是一個設置,使得程序可以在IDE中運行。
只需要調用entrypoint即可運行程序
from scrapy.cmdline import execute
execute(['scrapy', 'crawl', 'XiaoHua'])
來看具體分塊代碼實現:
1、items部分
# -*- coding: utf-8 -*-
# Define here the models for your scraped items
# See documentation in:
# http://doc.scrapy.org/en/latest/topics/items.html
import scrapy
class XiaohuaItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
siteURL=scrapy.Field() #首頁中各MM的URL
pageURL=scrapy.Field() #每一張圖片入口URL
detailURL=scrapy.Field() #圖片原圖地址
title=scrapy.Field() #MM標題
fileName=scrapy.Field() #文件夾名,每一個MM一個文件夾
path=scrapy.Field() #圖片存儲路徑(絕對路徑)
</br>
2、settings部分
# -*- coding: utf-8 -*-
# Scrapy settings for XiaoHua project
BOT_NAME = 'XiaoHua'
SPIDER_MODULES = ['XiaoHua.spiders']
NEWSPIDER_MODULE = 'XiaoHua.spiders'
#是否遵循機器人規則
ROBOTSTXT_OBEY = False
#默認是16,一次可以請求的最大次數
CONCURRENT_REQUESTS=32
#下載延遲
DOWNLOAD_DELAY=0.1
#Cookies設置
COOKIES_ENABLED = False
#headers設置
DEFAULT_REQUEST_HEADERS = {
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Encoding':'gzip, deflate, sdch',
'Accept-Language':'zh-CN,zh;q=0.8',
'Cache-Control':'max-age=0',
'Connection':'keep-alive',
'User-Agent':'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36'}
#管道設置
ITEM_PIPELINES = {'XiaoHua.pipelines.XiaohuaPipeline': 300}
</br>
3、spiders部分
# --coding:utf-8--
import scrapy
from XiaoHua.items import XiaohuaItem
from scrapy.http import Request
import requests
import re
import os
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
class Myspider(scrapy.Spider):
name='XiaoHua'
allowed_domains=['mmonly.cc']
base=r'F:/Desktop/code/info/XiaoHua/'
def start_requests(self):
#一共有6頁
for i in range(1,7):
url='https://www.mmonly.cc/tag/xh1/'+str(i)+'.html'
yield Request(url,callback=self.parse_one)
def parse_one(self,response):
#創建一個大的list存儲所有的item
items=[]
pattern=re.compile(r'<div class="title".*?<a.*?href="(.*?)">(.*?)</a></span></div>',re.S)
mains=re.findall(pattern,response.text)
for main in mains:
#創建實例,并轉化為字典
item=XiaohuaItem()
item['siteURL']=main[0]
item['title']=main[1]
item['fileName']=self.base+item['title']
items.append(item)
for item in items:
#創建文件夾
fileName=item['fileName']
if not os.path.exists(fileName):
os.makedirs(fileName)
#用meta傳入下一層
yield Request(url=item['siteURL'],meta={'item1':item},callback=self.parse_two)
def parse_two(self,response):
#傳入上面的item1
item2=response.meta['item1']
source=requests.get(response.url)
html=source.text.encode('utf-8')
#用正則提取頁數
pattern=re.compile(r'共(.*?)頁',re.S)
Num=re.search(pattern,html).group(1)
items=[]
for i in range(1,int(Num)+1):
#注意這里,創建實例的位置
item=XiaohuaItem()
item['fileName']=item2['fileName']
#構造每一個圖片的存儲路徑
item['path']=item['fileName']+'/'+str(i)+'.jpg'
#構造每一個圖片入口鏈接,以獲取源碼中的原圖鏈接
item['pageURL']=response.url[:-5]+'_'+str(i)+'.html'
items.append(item)
for item in items:
yield Request(url=item['pageURL'],meta={'item2':item},callback=self.parse_three)
def parse_three(self,response):
item=XiaohuaItem()
#傳入上面的item2
item3=response.meta['item2']
#匹配正則獲取圖片真實地址detailURL
pattern=re.compile(r'<li class="pic-down h-pic-down"><a target="_blank" class="down-btn" href=\'(.*?)\'>.*?</a>',re.S)
URL=re.search(pattern,response.text).group(1)
item['detailURL']=URL
item['path']=item3['path']
item['fileName']=item3['fileName']
yield item
</br>
4、pipelines部分
# -*- coding: utf-8 -*-
import requests
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
#用requests的get方法獲取圖片并保存入文件
class XiaohuaPipeline(object):
def process_item(self, item, spider):
detailURL=item['detailURL']
path=item['path']
fileName=item['fileName']
image=requests.get(detailURL)
f=open(path,'wb')
f.write(image.content)
f.close()
print u'正在保存圖片:',detailURL
print u'圖片路徑:',path
print u'文件:',fileName
return item
寫完代碼,直接調用entrypoint即可在IDE中運行(我用的Pycharm)
這個小項目我也放到github上了:https://github.com/LUCY78765580/Python-web-scraping/tree/master/XiaoHua (如果您覺得有幫助,可以star我喲~)
三、結果
最后結果就是這樣的:
</br>
四、參考:
meta傳參這一塊,參考了博客:
http://www.lxweimin.com/p/c77c59aa4b92
五、我分享我快樂
這里是你們要的小姐姐_:
百度網盤:https://pan.baidu.com/s/1bpxPRen
密碼:25gq
下載下來稍稍解壓即可,不用太感謝(順手點個贊就行),我是造福人類的小天使~
</br>
六、總結
最后,總結本篇關鍵:
1、Scrapy爬取多級網頁結構(主要用meta傳遞數據)
2、Scrapy爬取圖片的一般方法(別的方法放下次討論)
對了,不知各位有沒有發現,我們在爬唯一圖庫時,竟然如此順利,沒有遇到任何反爬。感嘆:良心網站呀
本篇就是這樣啦~