1 Item 封装数据
Item 类可以对爬取的数据进行封装,便于后续的处理、存储
封装步骤:
① 打开items.py
,进行修改
② 再spider中进入items类items 简单应用:
对图书名、作者数据进行封装
# items.py修改
import scrapy
from scrapy import Item,Field
class BookItem(Item):
name = Field()
price = Field()
# spider 修改
## '..items'表示返回上级菜单,找到items
from ..items import BookItem
class BookSpiderSpider(scrapy.Spider):
......
def parse(self, response):
for sel in response.css('article.product_pod'):
book = BookItem()
book['name'] = sel.xpath('./h3/a/@title').extract_first()
book['price'] = sel.css('p.price_color::text').extract_first()
......
- Field 元数据常用指令
# 1.将列表拼接成字符串(如拼接图书作者)
class BookItem(Item):
authors = Field(serializer=lambda x: '|'.join(x))
2 Item Pipeline 处理数据
- Item Pipeline 可以处理、存储数据
- 处理从 spider 发送的,由Item 封装的数据
- 页面数据抓取用spider解析,其他用Item Pipeline
- 主要的三个模块:
① process_item(item, spider):处理数据
② open_spider(self, spider):打开文件或数据库
③ close_spider(self, spider):关闭文件或数据库 - 处理数据步骤:
① 打开pipelines.py
,修改文件
② 打开setting.py
,修改配置文件 - 简单应用
图书价格汇率转换
# 1.修改pipelines.py文件
class PriceConverterPipeline(object):
# 英镑兑换人民币汇率
exchange_rate = 8.5309
def process_item(self, item, spider):
# 提取item的price 字段(如£53.74)
# 去掉前面英镑符号£,转换为float 类型,乘以汇率
price = float(item['price'][1:]) * self.exchange_rate
# 保留2 位小数,赋值回item的price 字段
item['price'] = '¥%.2f' % price
return item
# 2.修改setting.py文件
# 数字表示执行顺序
ITEM_PIPELINES = {
'example.pipelines.PriceConverterPipeline': 300,
}
3 数据存储
3.1 Exporter导出数据
- 使用Exporter导出数据
scrapy crawl books -o books.csv
- 指定文件路径时,可使用
%(name)s
和%(time)s
两个特殊变量
# %(name)s : 会被替换为spider的名字
# %(time)s : 会被替换成文件创建时间
scrapy crawl books -o 'export_data/%(name)s.csv'
scrapy crawl books -o 'export_data/%(time)s.csv'
scrapy crawl books -o 'export_data/%(name)s/%(time)s.csv'
3.2 mysql 数据存储
3.2.1 mysql 基本操作
将mysql添加进系统环境变量中
参考:怎么在cmd中输入mysql就可以进去mysql控制台登录数据库
$ mysql -hlocalhost -uroot -p0000
- 创建数据库
mysql> CREATE DATABASE scrapy_db CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
Query OK, 1 row affected (0.00 sec) - 使用数据库
mysql> USE scrapy_db;
Database changed - 创建表
mysql> CREATE TABLE books (
upc CHAR(16) NOT NULL PRIMARY KEY,
name VARCHAR(256) NOT NULL,
price VARCHAR(16) NOT NULL,
review_rating INT,
review_num INT,
stock INT
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.08 sec)
3.2.2 mysql python第三方库介绍
- 安装第三方库
conda install mysqlclient
- 常用指令
import MySQLdb
#连接数据库, 得到Connection 对象
conn = MySQLdb.connect(host='localhost', db='scrapy_db',
user='liushuo', passwd='12345678', charset='utf8')
#创建Curosr 对象,用来执行SQL语句
cur = conn.cursor()
#创建数据表
cur.execute('CREATE TABLE person (name VARCHAR(32), age INT, sex char(1)) ENGINE=InnoDB DEFAULT CHARSET=utf8')
#插入一条数据
cur.execute('INSERT INTO person VALUES (%s,%s,%s)', ('刘硕', 34, 'M'))
#保存变更,commit 后数据才被实际写入数据库
conn.commit()
#关闭连接
conn.close()
3.2.3 数据存入mysql(方法一)
- 第一步:编写pipelines.py
import MySQLdb
class MySQLPipeline:
def open_spider(self, spider):
db = spider.settings.get('MYSQL_DB_NAME', 'scrapy_default')
host = spider.settings.get('MYSQL_HOST', 'localhost')
port = spider.settings.get('MYSQL_PORT', 3306)
user = spider.settings.get('MYSQL_USER', 'root')
passwd = spider.settings.get('MYSQL_PASSWORD', 'root')
self.db_conn = MySQLdb.connect(host=host, port=port, db=db, user=user, passwd=passwd, charset='utf8')
self.db_cur = self.db_conn.cursor()
def close_spider(self, spider):
self.db_conn.commit()
self.db_conn.close()
def process_item(self, item, spider):
self.insert_db(item)
return item
def insert_db(self, item):
values = (
item['upc'],
item['name'],
item['price'],
item['review_rating'],
item['review_num'],
item['stock'],
)
sql = 'INSERT INTO books VALUES (%s,%s,%s,%s,%s,%s)'
self.db_cur.execute(sql, values)
- 第二步:修改 setting.py 文件
在配置文件settings.py中指定我们所要使用的MySQL数据库,并启用MySQLPipeline
MYSQL_DB_NAME = 'scrapy_db'
MYSQL_HOST = 'localhost'
MYSQL_USER = 'root'
MYSQL_PASSWORD = '0000'
ITEM_PIPELINES = {
'toscrape_book.pipelines.MySQLPipeline': 401,
}
3.2.4 基于adbapi模块的异步多线程存储(方法二)
from twisted.enterprise import adbapi
class MySQLAsyncPipeline:
def open_spider(self, spider):
db = spider.settings.get('MYSQL_DB_NAME', 'scrapy_default')
host = spider.settings.get('MYSQL_HOST', 'localhost')
port = spider.settings.get('MYSQL_PORT', 3306)
user = spider.settings.get('MYSQL_USER', 'root')
passwd = spider.settings.get('MYSQL_PASSWORD', 'root')
self.dbpool = adbapi.ConnectionPool('MySQLdb', host=host, db=db,user=user, passwd=passwd, charset='utf8')
def close_spider(self, spider):
self.dbpool.close()
def process_item(self, item, spider):
self.dbpool.runInteraction(self.insert_db, item)
return item
def insert_db(self, tx, item):
values = (
item['upc'],
item['name'],
item['price'],
item['review_rating'],
item['review_num'],
item['stock'],
)
sql = 'INSERT INTO books VALUES (%s,%s,%s,%s,%s,%s)'
tx.execute(sql, values)