一、Scrapy的日志等级
- 在使用 scrapy crawl 爬虫文件名 运行程序时,在终端里打印输出的就是scrapy的日志信息。
- 日志信息的种类:
ERROR : 一般错误
WARNING : 警告
INFO : 一般的信息
DEBUG : 调试信息
- 设置日志信息指定输出:
在settings.py配置文件中,加入
LOG_LEVEL = ‘指定日志信息种类’即可。
LOG_FILE = 'log.txt'则表示将日志信息写入到指定文件中进行存储。
例如:
LOG_LEVEL = ‘ERROR’ 绑定日志输出,只输出error类型的日志分析,其他类型的不输出
二、请求传参
- 在某些情况下,我们爬取的数据不在同一个页面中,例如,我们爬取一个电影网站,电影的名称,评分在一级页面,而要爬取的其他电影详情在其二级子页面中。这时我们就需要用到请求传参。
- 案例展示:爬取http://www.55xia.com/电影网,将一级页面中的电影名称,评分一级二级页面中的导演,电影介绍进行爬取。
实现代码:
爬虫文件代码:
import scrapy from filmPro.items import FilmproItem class FilmSpider(scrapy.Spider): name = 'film' # allowed_domains = ['www.xxxx.com'] start_urls = ['http://www.55xia.com/'] def parse(self, response): div_list = response.xpath('//div[@class="col-xs-1-5 movie-item"]') for div in div_list: # 1.获取解析到数据,并在items文件中配置属性 title = div.xpath('.//div[@class="meta"]/h1/a/text()').extract_first() grade = div.xpath('.//div[@class="meta"]/h1/em/text()').extract_first() if grade == None: grade = '0' # 1.获取详情页面 detail_url = 'https:' + div.xpath('.//div[@class="meta"]/h1/a/@href').extract_first() print(title,grade,detail_url) # 2.实例化一个item类型的对象 item = FilmproItem() item["title"] = title item["grade"] = grade # 3.对详情的url发送请求,通过meta参数进行Request的数据传递(请求传参) yield scrapy.Request(url=detail_url, callback=self.getDetailPage, meta={'item': item}) def getDetailPage(self,response): # 4.通过response获取item对象 item = response.meta["item"] # 5.获取详情压面解析到数据,并在items文件中配置属性 director = response.xpath('/html/body/div[1]/div/div/div[1]/div[1]/div[2]/table/tbody/tr[1]/td[2]/a/text()').extract_first() details = response.xpath('/html/body/div[1]/div/div/div[1]/div[2]/div[2]/p/text()').extract_first() item["director"] = director item["details"] = details yield item
items.py文件:
import scrapy class FilmproItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() title = scrapy.Field() # 获取电影的标题 grade = scrapy.Field() # 获取电影的评分 director = scrapy.Field() # 获取详情页面中电影的导演 details = scrapy.Field()# 获取详情页面中电影的简介
pipelines.py管道文件
class FilmproPipeline(object): fp = None def open_spider(self,spider): self.fp = open('./file.txt','w',encoding='utf-8') print("爬虫开始了!!!") def process_item(self, item, spider): self.fp.write(item['title'] + ":" + item['grade'] + ":" + item['director'] + item['details'] + " ") return item def close_spider(self,spider): self.fp.close() print("爬虫结束了!!!")
settiung.py配置文件
# 开启管道服务 ITEM_PIPELINES = { 'filmPro.pipelines.FilmproPipeline': 300, }
总结:
当使用scrapy进行数据爬取的时候,如果发现爬取的数据值没有在同一张页面中进行存储.
则必须使用请求传参进行处理(持久化存储),在scrapy框架中,使用meta()进行请求传参
三、如何提高scrapy的爬取效率
增加并发: 默认scrapy开启的并发线程为32个,可以适当进行增加。在settings配置文件中修改CONCURRENT_REQUESTS = 100值为100,并发设置成了为100。 降低日志级别: 在运行scrapy时,会有大量日志信息的输出,为了减少CPU的使用率。可以设置log输出信息为INFO或者ERROR即可。在配置文件中编写:LOG_LEVEL = ‘INFO’ 禁止cookie: 如果不是真的需要cookie,则在scrapy爬取数据时可以进制cookie从而减少CPU的使用率,提升爬取效率。在配置文件中编写:COOKIES_ENABLED = False 禁止重试: 对失败的HTTP进行重新请求(重试)会减慢爬取速度,因此可以禁止重试。在配置文件中编写:RETRY_ENABLED = False 减少下载超时: 如果对一个非常慢的链接进行爬取,减少下载超时可以能让卡住的链接快速被放弃,从而提升效率。在配置文件中进行编写:DOWNLOAD_TIMEOUT = 10 超时时间为10s
测试案例:
爬取4k高清壁纸图片 http://pic.netbian.com/
测试代码:
爬虫文件:
import scrapy from imagesPro.items import ImagesproItem class Image4kSpider(scrapy.Spider): name = 'image4K' # allowed_domains = ['www.xxx.com'] start_urls = ['http://www.xxx.com/'] url = "http://pic.netbian.com/index_%d.html" page = 1 def parse(self, response): li_list = response.xpath('//div[@class="slist"]/ul/li') for li in li_list: # 获取解析到数据值,并在items文件中设置属性 img_url ="http://pic.netbian.com" + li.xpath('./a/span/img/@src | ./a/img/@src').extract_first() img_name = li.xpath('./a/span/img/@alt | ./a/img/@alt').extract_first() #实例化item类型的对象,并将解析到的数据值储存到item对象中 item = ImagesproItem() item["img_name"] = img_name # 使用yield获取详情页面,通过meta参数进行Request的数据传递(请求传参) yield scrapy.Request(url=img_url,callback=self.img_name,meta={"item":item}) # 爬取多个分页页面 if self.page <10: self.page += 1 new_url = format(self.url%self.page) yield scrapy.Request(url=new_url,callback=self.parse) def img_name(self,response): # 通过response获取item对象 item = response.meta["item"] item["img_data"] = response.body yield item
items.py文件
import scrapy class ImagesproItem(scrapy.Item): # define the fields for your item here like: img_name = scrapy.Field() img_data = scrapy.Field()
pipelines.py(数据持久化存储)
import os class ImagesproPipeline(object): def open_spider(self,spider): if not os.path.exists("images"): os.mkdir("./images") def process_item(self, item, spider): imgPath = "./images" + item["img_name"] + ".jpg" with open(imgPath,"wb") as fp: fp.write(item["img_data"]) print(imgPath + "下载成功") return item
setting.py文件配置
ITEM_PIPELINES = { 'imagesPro.pipelines.ImagesproPipeline': 300, } CONCURRENT_REQUESTS = 10 # 默认开启10个线程 LOG_LEVEL = "ERROR" # 默认打印错误信息日志,如果没有则不打印 COOKIE_ENABLED = False # 警用cookie RETRY_ENABLED = False #禁止重试 DOWNLOAD_TIMEOUT = 10 # 设置超时时间