1. 程式人生 > >福利向---Scrapy爬蟲爬取多級圖片網站

福利向---Scrapy爬蟲爬取多級圖片網站

1.目標站分析

目標站網址為https://52zfl.vip/zhaifuli/list_2_1.html
每頁網址有若干連結,點選每個連結,是每部圖片資源的詳情頁面,由於圖片數量較多,涉及到翻頁操作。
通過分析頁面html程式碼,提取有用部分如下:

 		<article class="excerpt excerpt-one">
 			<header>
				<h2><a target="_blank" href="/zhaifuli/2018/0509/5141.html" title="微博女神閆盼盼12月VIP大尺度套圖[60P]">微博女神閆盼盼12月VIP大尺度套圖[60P]</
a
>
</h2> </header> </article>

用xpath程式碼可分別匹配為

  • 一級頁面內所有含二級頁面名稱和連結的程式碼塊:response.xpath('//article[@class="excerpt excerpt-one"]')
  • 每個程式碼塊中的名稱:xpath('./header/h2/a/text()').extract()[0]
  • 每個程式碼塊中的連結:'https://52zfl.vip'+xpath('./header/h2/a/@href').extract()[0]
  1. 每個二級頁面中圖片的連結:
<article class
="article-content">
<p> <img alt="微博女神閆盼盼2018年3月VIP大尺度套圖" src="https://www.images.zhaofulipic.com:8819/allimg/180509/150F52E1-0.jpg"> </p> <p> <img alt="微博女神閆盼盼2018年3月VIP大尺度套圖" src="https://www.images.zhaofulipic.com:8819/allimg/180509/150F55936-1.jpg"> </p> <p> <
img
alt="微博女神閆盼盼2018年3月VIP大尺度套圖" src="https://www.images.zhaofulipic.com:8819/allimg/180509/150F55560-2.jpg">
</p> <p> <img alt="微博女神閆盼盼2018年3月VIP大尺度套圖" src="https://www.images.zhaofulipic.com:8819/allimg/180509/150F5E27-3.jpg"> </p> </article>
  1. 每個二級頁面下一頁的網址格式:如本頁面為https://52zfl.vip/zhaifuli/2018/0509/5141.html則下一頁為https://52zfl.vip/zhaifuli/2018/0509/5141_1.html

2.建立爬蟲專案

切換至目標資料夾
scrapy startproject img
建立名為img的爬蟲專案

3.編寫爬蟲檔案

直接上原始碼,分析見註釋:

# -*- coding: utf-8 -*-
import scrapy
# 匯入item中結構化資料模板
from img.items import ImgItem
import time


class XhSpider(scrapy.Spider):
    # 爬蟲名稱,唯一
    name = "xh"
    # 允許訪問的域
    allowed_domains = ["52zfl.vip"]
    # 初始URL
    start_urls = ['https://52zfl.vip/zhaifuli/list_2_1.html']
 
    def parse(self, response):
        items = [] 
        #存放當前一級頁面下所有二級頁面資訊      
        if response.url.startswith("https://52zfl.vip/zhaifuli/list_2_"):
        # 如果圖片地址以https://52zfl.vip/zhaifuli/list_2_開頭,才取其名字及地址資訊
            allPics = response.xpath('//article[@class="excerpt excerpt-one"]') 
            #匹配一級頁面內所有含二級頁面名稱和連結的程式碼塊
            for pic in allPics:
                # 分別處理每個圖片,取出名稱及地址
                item = ImgItem()
                name = pic.xpath('./header/h2/a/text()').extract()[0]
                addr = pic.xpath('./header/h2/a/@href').extract()[0]
                count = self.findpage(name)
                #定義一個findpage()函式,計算當前二級頁面存在多少張圖片
                items.append(item)
                for page_item in items:
                #取每個二級頁面資訊,分別使用parse_page()函式進行抓取圖片地址
                    index = 1;#當前圖片計數
                    while count > 0:
                        if index == 1:
                            next_url = page_item['page_url']
                        else:
                            b = page_item['page_url']
                            next_url = b[:b.find('.html')]+"_%s.html" % index
                        count -= 4
                        index += 1
                        yield scrapy.Request(url=next_url, meta={'item_1': page_item},
                                             callback=self.parse_page)

                for i in range(1, 92):
                # 取得所有一級頁面網址,呼叫parse()函式,獲取二級頁面資訊
                    all_pages = 'https://52zfl.vip/zhaifuli/list_2_%s.html' % i
                    yield scrapy.Request(url=all_pages, callback=self.parse)

    def parse_page(self, response):
    #獲取每個二級頁面內圖片地址和其他資訊
        items = response.meta['item_1']
        infos = response.xpath('//article[@class="article-content"]/p/img')
        print(len(infos))
        current_milli_time = lambda: int(round(time.time() * 1000))
        for info in infos:
            item = ImgItem()
            images_urls = info.xpath('@src')[0].extract()
            item['pic_url'] = images_urls
            item['name'] = items['name']
            item['pic_name'] = str(current_milli_time())
            item['list_url'] = items['list_url']
            item['page_url'] = items['page_url']
            print(item)
            yield item

    def findpage(self,name):
        co = name[name.find('[') + 1:name.find(']') - 1]
        if co.isdigit():
            return int(co)
        else:
            return self.findpage(name[name.find(']')+1:])