Scrapy框架(基础命令、选择器、spider、Item Pipeline组件类,分布式架构)

基础命令

  1. scrapy3 startproject demo [project_dir]在project_dir目录下创建一个Scrapy项目。如果project_dir未指定,project_dir则与相同myproject。

  2. cd demo 进入到项目内

  3. scrapy genspider mydomain mydomain.com 创建一个蜘蛛爬虫

  4. 全局命令:
    startproject
    genspider
    settings
    runspider
    shell
    fetch
    view
    version
    仅项目命令:
    crawl
    check
    list
    parse
    -edit
    -bench

  5. scrapy crawl spidername 开始使用蜘蛛爬行

  6. scrapy check [-l] spidername 运行合同检查

  7. scrapy list 列出当前项目中所有可用的蜘蛛。输出是每行一个蜘蛛

  8. scrapy fetch [–option] url_name 使用Scrapy下载器下载给定的URL,并将内容写入标准输出。
    –nolog 不输出打印日志
    –headers:打印响应的HTTP头,而不是响应的正文
    –no-redirect:不遵循HTTP 3xx重定向(默认为遵循它们)

  9. scrapy view [–option] url_name 在浏览器中打开给定的URL,就像您的Scrapy蜘蛛会“看到”它一样。有时,蜘蛛看到的页面与普通用户的页面不同
    –no-redirect:不遵循HTTP 3xx重定向(默认为遵循它们)

  10. scrapy shell url_name 为给定的URL(如果给定)启动Scrapy shell,如果没有给定的URL,则为空。还支持UNIX样式的本地文件路径
    –no-redirect:不遵循HTTP 3xx重定向(默认为遵循它们
    response.text
    response.headers
    view(response)

  11. scrapy parse url_name [options] 使用随–callback选项传递的方法(parse如果未提供),获取给定的URL并与处理它的蜘蛛解析。

    callback或-c:蜘蛛方法,用作解析响应的回调, 调用

  12. scrapy settings [options] 获取Scrapy设置的值

    scrapy3 settings --get=DOWNLOADER_MIDDERWARES_BASE

  13. scrapy runspider spider_file.py 无需创建项目即可运行包含在Python文件中的蜘蛛程序。

  14. scrapy version [-v] 打印Scrapy版本。如果与-v它一起使用,还可以打印Python,Twisted和Platform信息,这对于错误报告很有

  15. scrapy crawl myspider -a category = electronics

    通过调用父类的初始化方法来获取category传来的参数(在父类的属性中)

    class Myspider(scrapy.Spider)
    	name = 'myspider'
    	
    	def __init__ (self,category=None,*args,**kwargs)
    		super(Myspider,self).__init__(*args,**kwargs)
    		self.category = category
    		
    	def parse(self,response)
    		self.logger.info(self.category)
    

选择器

  1. response.selector.xpath(’//span/text()’).extract_first()
    selector.xpath选择器(也可简写为.xpath)

  2. response.selector.css(‘title::text’).extract_first()
    selector.css选择器(也可简写为.css)

response.css(‘a::text()’) 提取元素文本
response.css(‘a::attr(src)’) 提取元素的属性值
extract(default=’’): 这个方法返回的是一个数组list对象,,里面包含了多个string,如果只有一个string,则返回[‘ABC’] default为找不到的默认值
extract_first():这个方法返回的是一个string字符串,是list数组里面的第一个字符串。

基本元素[属性]例:p[title]
基本元素[属性 = 值] //属性只有一个值 p[title = qiuqiu2]
基本元素[属性 = 值] 属性中做字符串拆分,只要能拆出来value这个词就行
基本元素[属性 ~= 值] //属性有多个值,空格隔开 p[title ~= qiuqiu1 abc]
基本元素[属性 ^= 值] //属性以特定值开始 p[title ^= qiuqiu]
基本元素[属性 $= 值] //属性以特定值结束 p[title $= bc]
获取属性值(html)里面的标签属性 response.css('a[href
=image] img::attr(src)’)
css选择器支持re(正则表达式) response.css(‘a::text’).re(‘None:(.*)’)

spider

对spider来说,爬取的循环类似下文:
  1. 以初始的URL初始化Request,并设置回调函数。 当该request下载完毕并返回时,将生成response,并作为参数传给该回调函数。

  2. spider中初始的request是通过调用 start_requests() 来获取的。 start_requests() 读取 start_urls 中的URL, 并以 parse 为回调函数生成 Request 。

  3. 在回调函数内分析返回的(网页)内容,返回 Item 对象或者 Request 或者一个包括二者的可迭代容器。 返回的Request对象之后会经过Scrapy处理,下载相应的内容,并调用设置的callback函数(函数可相同)。

  4. 在回调函数内,您可以使用 选择器(Selectors) (您也可以使用BeautifulSoup, lxml 或者您想用的任何解析器) 来分析网页内容,并根据分析的数据生成item。

  5. 最后,由spider返回的item将被存到数据库(由某些 Item Pipeline 处理)或使用 Feed exports 存入到文件中。

spider作为Spider子类的属性方法

属性
  • name, 定义spider名字的字符串(string)。spider的名字定义了Scrapy如何定位(并初始化)spider,所以其必须是唯一的。 不过您可以生成多个相同的spider实例(instance),这没有任何限制。 name是spider最重要的属性,而且是必须的

    name = ‘spider_name’

  • allowed_domains, 可选。包含了spider允许爬取的域名(domain)列表(list)。 当 OffsiteMiddleware 启用时, 域名不在列表中的URL不会被跟进

    allowed_domains = [‘leadingme.top’]

  • start_urls, URL列表。当没有制定特定的URL时,spider将从该列表中开始进行爬取。 因此,第一个被获取到的页面的URL将是该列表之一。 后续的URL将会从获取到的数据中提取

    start_urls = [‘http://leadingme.top/’]

  • custom_settings, 运行此Spider时将从项目范围的配置中覆盖的设置字典。由于必须在实例化之前更新设置,因此必须将其定义为类属性。

    custom_settings = {
    	DEFAULT_REQUEST_HEADERS : {
    	  'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    	  'Accept-Language': 'en',
    	}
    }
    

方法

  • from_crawler(crawler,* args,** kwargs) 此方法 在新实例中设置crawler和settings属性,因此以后可以在Spider代码中对其进行访问

    @classmethod
    return cls(
               mongo_url=crawler.settings.get('MONGO_URL'),
               mongo_db = crawler.settings.get('MONGO_DB')
        )
    
  • start_requests() 当指定了URL时,make_requests_from_url()将被调用来创建Request对象。该方法仅会被Scrapy调用一次,因此您可以将其实现为生成器。该方法的替代实现是使用start_urls的url生成Request。
    默认的是get请求,可以改写start_requests()方法为post请求

    def start_requests(self):
    	yield scrapy.Requests(url='http://httpbin.org/post',method='POST',callback=self.parse)
    
  • make_requests_from_url(url) 该方法Request在start_requests()初始化请求时被调用,也被用于转化URL为请求。

    修改了默认的回调函数,次方法默认被start_requests调用,如果重写start _requests,则makemake_requests_from_url失效

     	def start_requests(self):
     		yield scrapy.Requests(url='www.baidu.com',callback=self.parse_index
     	def make_requests_from_url(self):
     		yield scrapy.Requests(url=url,callback=self.parse_index)
     	
     	def parse(self, response):
     		print('Baidu', response.status)
       ```
    
  • parse(response) 当response没有指定指定函数时,该方法是Scrapy处理下载的response的替代方法。parse负责处理response并返回处理的数据以及(/或)跟进的URL。 Spider对其他的请求的副本函数也有相同的要求。如果生成一个item对象,则返回给itempipeline处理,如果生成Request对象,则会被接入到start_urls(url队列中),等待start-requests调用

    	yiely item
    	yiely scrapy.Request(url=url,callback=self.parse)
    
  • log(message[,level,component])使用scrapy.log.msg()方法记录(log)消息。log中自动带上该蜘蛛的name属性,通过调用self.logger实例对象的方法实现

    CRITICAL - 严重错误(critical)
    ERROR - 一般错误(regular errors)
    WARNING - 警告信息(warning messages)
    INFO - 一般信息(informational messages)
    DEBUG - 调试信息(debugging messages)

	from scrapy import log
	log.msg("This is a warning", level=log.WARNING)
	def parse(response):
		self.logger.info(response.status)  控制台输出INFO:200的调试信息 
  • closed(reason) 当spider关闭时,该函数被调用。

Item Pipeline组件类

  • 简介

    当Item在Spider中被收集之后,它将会被传递到Item Pipeline,一些组件会按照一定的顺序执行对Item的处理。每个item pipeline组件(有时称之为“Item Pipeline”)是实现了简单方法的Python类。他们接收到Item并通过它执行一些行为,同时也决定此Item是否继续通过pipeline,或是被丢弃而不再进行处理。
    一般用于以下情景:
    - 清理HTML数据
    - 验证爬取的数据(检查item包含某些字段)
    - 查重(并丢弃)
    - 将爬取结果保存到数据库中

  • process_item(self, item, spider) 每个item pipeline组件都需要调用该方法,这个方法必须返回一个 Item (或任何继承类)对象, 或是抛出 DropItem 异常,被丢弃的item将不会被之后的pipeline组件所处理。(返回的值给优先级后面的Pipeline处理)

  • open_spider(self, spider) 当spider被开启时,这个方法被调用。

  • close_spider(spider) 当spider被关闭时,这个方法被调用

  • from_cralwer(cls, crawler)类方法 此方法 在新实例中设置crawler.settings属性,因此以后可以在Spider代码中对其进行访问

补充

  • 写入json文件
import json
class JsonWriterPipeline(object):

    def __init__(self):
        self.file = open('items.jl', 'wb')

    def process_item(self, item, spider):
        line = json.dumps(dict(item)) + "\n"
        self.file.write(line)

	#  存储到MongoDB
import pymongo

class MongoPipeline(object):

    def __init__(self, mongo_uri, mongo_db):
        self.mongo_uri = mongo_uri
        self.mongo_db = mongo_db

    @classmethod
    def from_crawler(cls, crawler):
		# 相当于用 类(a,b)创建并返回了一个实例对象
        return cls(
            mongo_uri=crawler.settings.get('MONGO_URI'),
            mongo_db=crawler.settings.get('MONGO_DATABASE', 'items')
        )

    def open_spider(self, spider):
        self.client = pymongo.MongoClient(self.mongo_uri)
        self.db = self.client[self.mongo_db]

    def close_spider(self, spider):
        self.client.close()

    def process_item(self, item, spider):
        collection_name = item.__class__.__name__
        self.db[collection_name].insert(dict(item))
        return item
  • 去重
from scrapy.exceptions import DropItem

class DuplicatesPipeline(object):

    def __init__(self):
		# set()  函数创建一个无序不重复元素集,可进行关系测试,删除重复数据,还可以计算交集、差集、并集等 如 set([1,2,3])|set([4,5,6]) = set([1,2,3,4,5,6])
        self.ids_seen = set()

    def process_item(self, item, spider):
        if item['id'] in self.ids_seen:
			# 删除该item,并抛出异常
            raise DropItem("Duplicate item found: %s" % item)
        else:
            self.ids_seen.add(item['id'])
            return item
  • 启用一个Pipeline组件类
ITEM_PIPELINES = {
    'myproject.pipelines.PricePipeline': 300,
    'myproject.pipelines.JsonWriterPipeline': 800,
}
分配给每个类的整型值,确定了他们运行的顺序,item按数字从低到高的顺序,通过pipeline,通常将这些数字定义在0-1000范围内。

Scrapy分布式架构

  1. Redis队列
  • Redis,非关系型数据库,Key-Value形式存储,结构灵活
  • 是内存中的数据结构存储系统,处理速度快,性能好
  • 提供队列,集合多种存储结构,方便队列维护
  1. Request去重(使用Redis集合)
  • Redis提供集合数据结构,在Redis集合中存储每个Requests的指纹(id)
  • 在向Request队列中加入Request前首先验证这个Request的指纹是否已经加入到集合中,如果不存在,则将Request添加入队列并将指纹加入集合
  1. 防止中断
  • 在每台从机Scrapy启动时都会首先判断当前Redis Requets队列是否为空
  • 如果不为空,则从队列中取得下一个Request执行爬取
  • 如果为空,则重新开始爬取,第一台从机执行爬取向队列中添加Request
  1. Scrapy-Redis
  • Scrapy-Redis库实现了分布式架构,改写了Scrapy的调度器,队列等组件。利用它可以方便地实现Scrapy分布式架构
发布了54 篇原创文章 · 获赞 24 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_43388615/article/details/105271499
今日推荐