继续入门示例Demo项目:

项目默认已经创建好了items和 pipelines
Items
爬取的主要目标就是从非结构性的数据源提取结构性数据,例如网页。 Scrapy spider可以以python的dict来返回提取的数据.虽然dict很方便,并且用起来也熟悉,但是其缺少结构性,容易打错字段的名字或者返回不一致的数据,尤其在具有多个spider的大项目中。。
为了定义常用的输出数据,Scrapy提供了 Item 类。 Item 对象是种简单的容器,保存了爬取到得数据。 其提供了 类似于词典(dictionary-like) 的API以及用于声明可用字段的简单语法。
许多Scrapy组件使用了Item提供的额外信息: exporter根据Item声明的字段来导出数据、 序列化可以通过Item字段的元数据(metadata)来定义、 trackref 追踪Item实例来帮助寻找内存泄露 (see 使用 trackref 调试内存泄露) 等等。
Item Pipeline
当Item在Spider中被收集之后,它将会被传递到Item Pipeline,一些组件会按照一定的顺序执行对Item的处理。
每个item pipeline组件(有时称之为“Item Pipeline”)是实现了简单方法的Python类。他们接收到Item并通过它执行一些行为,同时也决定此Item是否继续通过pipeline,或是被丢弃而不再进行处理。
以下是item pipeline的一些典型应用:
清理HTML数据
验证爬取的数据(检查item包含某些字段)
查重(并丢弃)
将爬取结果保存到数据库中
items.py默认代码:
# -*- coding: utf-8 -*- # Define here the models for your scraped items # # See documentation in: # https://doc.scrapy.org/en/latest/topics/items.html import scrapy class DemoItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() pass
pipelines.py默认代码:
class DemoPipeline(object): def process_item(self, item, spider): return item
自定义items:
import scrapy class DemoItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() title = scrapy.Field() # 存储标题 url = scrapy.Field() # 存储地址
在pipelines中对数据就行清洗:
class DemoPipeline(object): def process_item(self, item, spider): title = item["title"] url = item["url"] """这里插入数据操作代码 比如写入数据库之类的操作""" return item
回到spiders (dev456.py)文件中, 使用刚刚定义的item:
# -*- coding: utf-8 -*-
import scrapy
from demo.items import DemoItem
class Dev456Spider(scrapy.Spider):
name = 'dev456'
allowed_domains = ['456dev.com']
start_urls = ['http://www.456dev.com/list-1.html']
def parse(self, response):
titles = response.xpath("//li/a[contains(@class, 'title')]/text()").extract()
urls = response.xpath("//li/a[contains(@class, 'title')]/@href").extract()
for title, url in zip(titles, urls):
item = DemoItem()
item["title"] = title
item["url"] = response.urljoin(url)
yield item最后在settings.py中启用pipelines, 取消注释启用默认item pipeline:

执行结果:

一下子跑完了,因为这只是一页的数据,如何抓取整个栏目的数据呢:

通过分析,我们可以知道只要让spider继续请求分页地址解析数据就行了:
# -*- coding: utf-8 -*-
import scrapy
from demo.items import DemoItem
class Dev456Spider(scrapy.Spider):
name = 'dev456'
allowed_domains = ['456dev.com']
start_urls = ['http://www.456dev.com/list-1.html']
def parse(self, response):
titles = response.xpath("//li/a[contains(@class, 'title')]/text()").extract()
urls = response.xpath("//li/a[contains(@class, 'title')]/@href").extract()
for title, url in zip(titles, urls):
item = DemoItem()
item["title"] = title
item["url"] = response.urljoin(url)
yield item
# 下一页数据
next_url_list = response.xpath("//li[contains(@class, 'next')]/a/@href").extract()
if next_url_list:
# 新请求
yield scrapy.Request(response.urljoin(next_url_list[0]))新请求默认继续调用parse方法解析数据,循环下去,直到没有下页数据时停止.
附上完整的项目代码:

