在使用scrapy crawl spiderFileName運行程序時,在終端裏打印輸出的就是scrapy的日誌信息。html
在settings.py配置文件中任意位置加入:python
# 設置終端輸出指定種類的日誌信息 LOG_LEVEL = 'ERROR' # 只打印ERROR級別的日誌信息
將日誌信息存儲在指定文件中,而再也不顯示在終端裏:web
# 設置終端輸出指定種類的日誌信息 LOG_LEVEL = 'ERROR' # 只打印ERROR級別的日誌信息 LOG_FILE = 'log.txt' # 指定日誌存儲到一個文件中
請求傳參針對場景:爬取的數據值不在同一個頁面中。
需求:將id97電影網站中電影詳情數據進行爬取(名稱、類型、導演、語言、片長)json
meta參數可實現item對象的傳遞。scrapy.Request()方法中有一個參數meta.經過meta能夠將items對象傳遞給回調函數。
注意:meta只能接收字典類型的數據值。所以須要將items封裝到字典中,將字典賦值給meta參數,meta就能夠將字典傳遞給回調函數。dom
def parse(self, response): div_list = response.xpath('/html/body/div[1]/div[1]/div[2]/div') # 獲取/html/body/div[1]/div[1]/div[2]下全部子div for div in div_list: """省略代碼""" # 建立items對象 item = MovieproItem() item['name'] = name item['kind'] = kind # 手動發起請求 yield scrapy.Request(url=url, callback=self.parseBySecondPage, meta={'item': item})
隨後能夠在parseBySecondPage函數中取出Request方法的meta參數傳遞過來的字典。
取出方法是response.meta,以下所示:scrapy
def parseBySecondPage(self, response): """專門用於解析二級子頁面中的數據值""" # 取出Request方法的meta參數傳遞過來的字典:取出方法是response.meta item = response.meta['item'] item['actor'] = actor item['language'] = language item['longTime'] = longTime
import scrapy from moviePro.items import MovieproItem class MovieSpider(scrapy.Spider): name = 'movie' # allowed_domains = ['www.id97.com'] start_urls = ['https://www.55xia.com/movie'] # 網站地址更改。。 def parseBySecondPage(self, response): """專門用於解析二級子頁面中的數據值""" # 導演、語言、片長 actor = response.xpath('/html/body/div[1]/div/div/div[1]/div[1]/div[2]/table/tbody/tr[1]/td[2]/a/text()').extract_first() language = response.xpath('/html/body/div[1]/div/div/div[1]/div[1]/div[2]/table/tbody/tr[6]/td[1]/text()').extract_first() longTime = response.xpath('/html/body/div[1]/div/div/div[1]/div[1]/div[2]/table/tbody/tr[8]/td[2]/text()').extract_first() # 取出Request方法的meta參數傳遞過來的字典:取出方法是response.meta item = response.meta['item'] item['actor'] = actor item['language'] = language item['longTime'] = longTime # 將item提交給管道 yield item def parse(self, response): # 名稱、類型、導演、語言、片長 div_list = response.xpath('/html/body/div[1]/div[1]/div[2]/div') # 獲取/html/body/div[1]/div[1]/div[2]下全部子div for div in div_list: # 電影名稱 name = div.xpath('.//div[@class="meta"]/h1/a/text()').extract_first() # 電影種類: //text() 該div下全部文本數據均獲取 # 以下xpath方法返回的是一個列表,且列表長度爲4 kind = div.xpath('.//div[@class="otherinfo"]//text()').extract() # 將kind列表轉化爲字符串 kind = "".join(kind) # 影片詳情url url = div.xpath('.//div[@class="meta"]/h1/a/@href').extract_first() # 建立items對象 item = MovieproItem() item['name'] = name item['kind'] = kind # 問題:如何將兩個方法解析的電影詳情數據存儲到一個item對象中——meta # 下一步:對url發起請求,獲取頁面數據,進行指定數據解析 # 手動發起請求 yield scrapy.Request(url=url, callback=self.parseBySecondPage, meta={'item': item})
import scrapy class MovieproItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() # 封裝全部屬性 name = scrapy.Field() kind = scrapy.Field() actor = scrapy.Field() language = scrapy.Field() longTime = scrapy.Field()
import json class MovieproPipeline(object): fp = None def open_spider(self, spider): self.fp = open('movie.txt', 'w', encoding='utf-8') def process_item(self, item, spider): # detail = item['name'] + ':' + item['kind'] + ':' + item['actor'] + ':' + item['language'] + ':' + item['longTile'] + '\n\n\n' detail = dict(item) json.dump(detail, self.fp, ensure_ascii=False) return item def close_spider(self, spider ): self.fp.close()
# Crawl responsibly by identifying yourself (and your website) on the user-agent USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36' # 假裝請求載體身份 # Obey robots.txt rules ROBOTSTXT_OBEY = False # 不聽從門戶網站robots協議,避免某些信息爬取不到 # Configure item pipelines # See https://doc.scrapy.org/en/latest/topics/item-pipeline.html ITEM_PIPELINES = { 'moviePro.pipelines.MovieproPipeline': 300, }
kind = div.xpath('.//div[@class="otherinfo"]//text()').extract() # 將kind列表轉化爲字符串 kind = "".join(kind)
解析它的xpath方法返回的是一個列表,且列表長度爲4。所以不能再使用extract_first方法,要使用extract()方法獲取列表。
獲取列表後須要將列表轉化爲字符串。在這裏使用"".join(list)實現。ide
# 方法一:拼接字符串寫入文件中 def process_item(self, item, spider): detail = item['name'] + ':' + item['kind'] + ':' + item['actor'] + ':' + item['language'] + ':' + item['longTile'] + '\n\n\n' self.fp.write(detail) return item # 方法二:json.dump()將dict類型的數據轉成str,並寫入到json文件中 def process_item(self, item, spider): detail = dict(item) json.dump(detail, self.fp, ensure_ascii=False) return item