scrapy item、scrapy pipelines
写在前面
本片笔记和 python 爬虫 5 (scrapy重爬世界大学排名)使用的同一个项目
1、scrapy item
Items是将要装载抓取的数据的容器,它工作方式像python里面的字典,但它提供更多的保护,比如对未定义的字段填充以防止拼写错误。
1.1、开始写代码
在项目里找到items.py
使用items来装载我们抓取的数据
# -*- coding: utf-8 -*-
import scrapy
class UniversityItem(scrapy.Item):
name = scrapy.Field()
country = scrapy.Field()
1.1.1、使用scrapy shell测试UniversityItem对象
在虚拟环境下安装ipython
测试请求url
scrapy shell http://www.qianmu.org/%E9%BA%BB%E7%9C%81%E7%90%86%E5%B7%A5%E5%AD%A6%E9%99%A2
创建UniversityItem对象,并查看类型
测试u的取值:测试结果发现u和字典几乎一样
u只能设置UniversityItem对象里已经存在的kay
1.1.2、修改usnews.py
目前usnews.py所有代码
# -*- coding: utf-8 -*-
import scrapy
# scrapy异步请求数据
from qianmo.items import UniversityItem
class UsnewsSpider(scrapy.Spider):
name = 'usnews'
# allowed_domains允许爬的url必须要在此字段内
allowed_domains = ['qianmu.org']
# start_urls可以设置多个
start_urls = ['http://www.qianmu.org/ranking/1528.htm']
# start_urls请求成功后就会调用parse方法
def parse(self, response):
# extract()返回的是一个列表类型的数据
urls = response.xpath("//div[@class='rankItem']//tr/td[2]//a/@href").extract()
for url in urls:
if not url.startswith("http://www.qianmu.org"):
url = "http://www.qianmu.org/%s" % url
yield response.follow(url, self.parse_university)
def parse_university(self, response):
"""处理大学详情页面"""
response = response.replace(
body=response.text.replace('\t', '').replace('\r\n', '')
)
item = UniversityItem()
data = {}
item['name'] = response.xpath("//div[@class='wikiContent']/h1/text()").extract_first()
table = response.xpath("//div[@class='wikiContent']//table")[0]
k = table.xpath(".//td[1]/p/text()").extract()
cols = table.xpath(".//td[2]")
v = [" ".join(col.xpath('.//text()').extract_first()) for col in cols]
data.update(zip(k, v))
item['country'] = data.get("国家")
yield item
2、scrapy pipelines
pipelines:管道模块,处理spider模块分析好的结构化数据,如保存入库等
2.1、用mysql储存
在虚拟环境下安装pymysql:pip install pymysql
然后在settings.py打开ITEM_PIPELINES(记得改QianmoPipeline为MysqlPipeline)
2.1.1、配置数据库
pipelines.py:配置数据库
这里有个知识点zip(*)
c=zip(a,b)打包成字典
a,b=zip(*c)解压字典
# -*- coding: utf-8 -*-
import pymysql
class MysqlPipeline(object):
def open_spider(self, spider):
self.conn = pymysql.connect(
host="127.0.0.1",
port=3306,
db="scrapy01",
user="root",
password="root",
charset="utf8",
)
self.cur = self.conn.cursor()
def close_spider(self, spider):
self.cur.close()
self.conn.close()
def process_item(self, item, spider):
keys, values = zip(*item.items())
sql = "insert into universities ({}) value ({})".format(
','.join(keys),
','.join(['%s']*len(values))
)
self.cur.execute(sql, values)
self.conn.commit()
# 显示sql语句
print(self.cur._last_executed)
return item
登录然后创建scrapy01
# 这里我的用户名密码都是root
mysql -uroot -proot
# 创建scrapy01
create database scrapy01;
# 退出
exit;
打开图形化界面
新建表
创建表创建字段:name(主键、不允许为空)、country
运行试试
查看数据库
2.2、用redis储存
在虚拟环境安装redis:pip install redis
在setting配置reids
启动redis
写代码
from scrapy.exceptions import DropItem
class RedisPipeline(object):
def open_spider(self, spider):
self.r = redis.Redis(host='127.0.0.1')
def process_item(self, item, spider):
if self.r.sadd(spider.name, item['name']):
return item
# 如果添加name失败就自动删除item,并停止执行process_item
raise DropItem
打开一个新的cmd窗口进入redis环境
清空一下redis
redis:flushdb(注意这个代码会清空redis里面所有数据)
reids先别关闭,现在进入pycharm,登录mysql
清空mysql里的universities表
mysql:truncate table universities;(注意这个代码会清空universities表里面所有数据,且不可恢复)
运行项目
查看一下redis里面存了多少条数据:
查看存了多少条数据
scard usnews
查看一下mysql里面存了多少条数据: select count(*) from universities;