1. 程式人生 > >重寫第一個爬蟲程式

重寫第一個爬蟲程式

第一個爬蟲程式是利用scrapy命令建立好之後,直接編寫程式碼實現的。文章見 [
scrapy 從第一個爬蟲開始
],本文將利用item,pipeline以及檔案儲存重寫此程式,從而使大家更好的理解。

一、首先是image.py程式

# -*- coding: utf-8 -*-
import scrapy
from image.items import ImageItem
from scrapy.http import Request
import sys
 
class ImageSpider(scrapy.Spider):
    name = 'image'
    allowed_domains = ['xdcd.com']

    base = 'https://xkcd.com/'
    start_urls = ['https://xkcd.com/1']
    
    def parse(self, response):
    	item = ImageItem()
    	item['title'] = ''
    	item['url'] = ''

    	item['title'] = response.xpath('//div[@id="ctitle"]/text()').extract()[0]

    	for urlSelector in response.xpath('//div[@id="comic"]'):
    		urls = urlSelector.xpath('img/@src').extract()
    		
    		if len(urls):
    			item['url'] = 'https:' + urls[0]
    		else:
    			urls = urlSelector.xpath('a/img/@src').extract()
    			if len(urls):
    				item['url'] = 'https:' + urls[0]

    		if item['title'] and item['url']:
    			yield item

    	nextPageSelector = response.xpath('//div[@id="middleContainer"]/ul[@class="comicNav"]')
    	urlStr = nextPageSelector.xpath('li/a/@href').extract()[3]
    	urlArr = urlStr.split('/')
    	print(urlArr)
    	if len(urlArr) >= 2:
    		nextPageUrl = self.base + str(urlArr[1]) + '/'
    		yield Request(nextPageUrl, callback=self.parse, dont_filter = True)

這段程式碼的改動包括以下幾個方面:
1 從當前頁獲取下一頁的url,而不是把設定start_urls為所有的頁面url,更接近實際

2 使用了item,item是要爬取的資料結構定義,比如這裡我們定義了title,url兩個欄位,程式碼在items.py裡,注意引入方式

3 利用yield關鍵把item傳遞給pipeline進行清洗,過濾或者持久化處理;同時利用yield處理下一頁的請求,注意引數為url,回撥函式即處理response的函式名稱,第三個引數告訴爬蟲不進行過濾處理,否則會被去重過濾掉

yield Request(nextPageUrl, callback=self.parse, dont_filter = True)

二、items.py程式

# -*- coding: utf-8 -*-

import scrapy
class ImageItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    title = scrapy.Field()
    url = scrapy.Field()

三、pipelines.py程式

# -*- coding: utf-8 -*-

# Define your item pipelines here
import json

class ImagePipeline(object):
	def __init__(self):
		self.file = open('data.json', 'wb')

	def process_item(self, item, spider):
		line = json.dumps(dict(item)) + "\n"
		self.file.write(line.encode())
		return item

這裡就是處理item,過濾或者持久化,此處是儲存到data.json檔案裡,注意這裡line需要呼叫encode方法,否則會報錯,大概是兩種string型別的問題。

到此,第一個爬蟲程式就重新完成了,也更清楚利用scrapy進行資料爬取的整個資料流程。