版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_39532362/article/details/88197638
python_爬虫_scrapy_pipelines用法
创建项目
scrapy start project images360 #生成项目文件
scrapy genspider images images.so.com #创建一个新的spider,命名images,url为images.so.com
全局设置
settings.py里去掉注解及加入代码
# 忽略协议
ROBOTSTXT_OBEY = False
# 设置爬取得最大页数
max_page=50
# 开启管道,数值越少越优先处理
ITEM_PIPELINES = {
'image360.pipelines.Image360Pipeline': 300,
'image360.pipelines.Image360Pipeline_MySql': 400,
}
# 定义用于连接数据库的参数
MYSQL_HOST='localhost'
MYSQL_DATABASE='scrapy_test'
MYSQL_USER='root'
MYSQL_PASSWORD='123456'
MYSQL_PORT=3306
设置Item
items.py里编写item类
import scrapy
class Image360Item(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
collection=tabe='images'
id=scrapy.Field()
url=scrapy.Field()
title=scrapy.Field()
thumb=scrapy.Field()
编写spider
images.py里编写spider
# -*- coding: utf-8 -*-
import scrapy
import urllib
import json
from image360.items import Image360Item
class ImagesSpider(scrapy.Spider):
name = 'images'
allowed_domains = ['images.so.com']
start_urls = ['http://images.so.com/']
# 重写start_requests生成30个请求,相当于start_urls设置30个链接
def start_requests(self):
# 解析网址,并设置其他不变的请求参数
def urldecode(word):
kvs=[kv for kv in word.split('&')]
data=dict([tuple(kv.split('=')) for kv in kvs])
return data
word=r'ch=beauty&t1=595&src=banner_beauty&gid=964b6885fd605285a991a16988403f68&sn=60&listtype=new&temp=1'
data=urldecode(word)
base_url='http://image.so.com/zj?'
for page in range(1,self.settings.get('MAX_PAGE')+1):
data['sn']=page*30
params=urllib.parse.urlencode(data)
url=base_url+params
yield scrapy.Request(url,self.parse)
# 解析爬取结果
def parse(self, response):
result=json.loads(response.text)
for image in result.get('list')[:10]:
print('====>spider.parse')
item=Image360Item()
item['id']=image.get('imageid')
item['url']=image.get('qhimg_url')
item['title']=image.get('group_title')
item['thumb']=image.get('qhimg_thumb_url')
yield item
设置pipeline
直接设置
简单item处理
import requests
from scrapy.exceptions import DropItem
# 基本item处理
class Image360Pipeline(object):
# 对图片链接数据实现保存
def process_item(self,item,spider):
response=requests.get(item['url'])
with open('./images/%s'%item['url'].split('/')[-1],'wb') as f:
f.write(response.content)
写入数据库
# 写进mysql
import pymysql
from scrapy.exceptions import DropItem
class Image360Pipeline_MySql(object):
def __init__(self,host,database,user,password,port):
self.host=host
self.database=database
self.user=user
self.password=password
self.port=port
# 用setting变量初始化自身对象
@classmethod
def from_crawler(cls,crawler):
return cls(
host=crawler.settings.get('MYSQL_HOST'),
database=crawler.settings.get('MYSQL_DATABASE'),
user=crawler.settings.get('MYSQL_USER'),
password=crawler.settings.get('MYSQL_PASSWORD'),
port=crawler.settings.get('MYSQL_PORT'),
)
# spider开启时调用链接数据库
def open_spider(self,spider):
self.db=pymysql.connect(host=self.host,database=self.database,user=self.user,password=self.password,port=self.port,charset='utf8')
self.cursor=self.db.cursor()
# spider关闭时调用断开数据库
def close_spider(self,spider):
self.db.close()
# 处理item,把item写入数据库并返回item
def process_item(self,item,spider):
data=dict(item)
keys=','.join(data.keys())
values=','.join(['%s']*len(data))
# 这里需要事在数据库中创建表
sql='insert into %s (%s) values (%s)'%('images',keys,values)
self.cursor.execute(sql,tuple(data.values()))
self.db.commit()
return item
相关解析
- process_item(self,item,spider)
【item处理的主要内容在这里设置,必须返回item待可能继续的处理】
item:就是被spider返回的item
spider - from_crawler(cls,crawler)
【用于初始化自身的函数,cls就是调用自身的__init__】 - open_spider(self,spider)
【spider启动时执行调用】 - close_spider(self,spider)
【spider关闭时时执行调用】
ImagesPipeline继承类设置
全局设置
settings.py去掉注解及加入代码
# 定义存储文件路径
`IMAGES_STORE='./images'`
编写代码
import scrapy
from scrapy.exceptions import DropItem
from scrapy.pipelines.images import ImagesPipeline
class Image360Pipeline(ImagesPipeline):
# 处理item并返回新的请求
def get_media_requests(self,item,info):
yield scrapy.Request(item['url']) #可以指定callback函数
# 根据对应的下载请求设置文件名
def file_path(self,request,response=None,info=None):
return request.url.split('/')[-1]
# 根据对应的下载结果判断是否成功
def item_completed(self,results,item,info):
image_paths=[x['path'] for ok,x in results if ok]
if not image_paths:
raise DropItem('Image Downloaded Failed')
return item
相关解析
- class scrapy.pipelines.images.ImagesPipeline
【一个高效率下载及保存图片的类,编写一个新的pipeline继承此类】 - get_media_requests(item,info)
【接收item,可根据其生成Request对象,返回的Request加入调度,等待执行下载】 - file_path(request,response,info)
【用于设置保存的文件名或路径】
request:对应当前下载的Request对象
response:本例需要设置为None
info:本例需要设置为None - item_completed(self,results,item,info)
【待新的下载完成后,处理对应的item对象】
results:对应item的下载结果,列表形式,元素为元祖,包含成功标识信息及链接信息