zoukankan      html  css  js  c++  java
  • 爬虫-scrpay

    Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。 其可以应用在数据挖掘,信息处理或存储历史数据等一系列的程序中。
    其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的, 也可以应用在获取API所返回的数据(例如 Amazon Associates Web Services ) 或者通用的网络爬虫。Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试。

    Scrapy 使用了 Twisted异步网络库来处理网络通讯。整体架构大致如下

    Scrapy主要包括了以下组件:

      • 引擎(Scrapy)
        用来处理整个系统的数据流处理, 触发事务(框架核心)
      • 调度器(Scheduler)
        用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址
      • 下载器(Downloader)
        用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)
      • 爬虫(Spiders)
        爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面
      • 项目管道(Pipeline)
        负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。
      • 下载器中间件(Downloader Middlewares)
        位于Scrapy引擎和下载器之间的框架,主要是处理Scrapy引擎与下载器之间的请求及响应。
      • 爬虫中间件(Spider Middlewares)
        介于Scrapy引擎和爬虫之间的框架,主要工作是处理蜘蛛的响应输入和请求输出。

    现在的scrapy的中间件里面没有了调度中间件了。

    Scrapy运行流程大概如下:

    1. 引擎从调度器中取出一个链接(URL)用于接下来的抓取
    2. 引擎把URL封装成一个请求(Request)传给下载器
    3. 下载器通过twisted从互联网中把资源下载下来,并封装成应答包(Response)
    4. 爬虫解析Response
    5. yield实体(Item),则交给实体管道进行持久化的处理。
    6. yield链接(URL),则把URL交给调度器等待抓取;相当于再一次的发送请求

     一、安装

      

    Linux
          pip3 install scrapy
     
     
    Windows
          a. pip3 install wheel
          b. 下载twisted http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
          c. 进入下载目录,执行 pip3 install Twisted‑17.1.0‑cp35‑cp35m‑win_amd64.whl
          d. pip3 install scrapy
          e. 下载并安装pywin32:https://sourceforge.net/projects/pywin32/files/
    

    二、基本使用

    1. 基本命令

    1. scrapy startproject  项目名称
       - 在当前目录中创建中创建一个项目文件(类似于Django)
     
    2. scrapy genspider  <name> <domain>
       - 创建爬虫应用
       如:
          scrapy gensipider oldboy oldboy.com
          scrapy gensipider autohome autohome.com.cn
       PS:
          查看所有命令:scrapy gensipider -l
          查看模板命令:scrapy gensipider -d 模板名称
     
    3. scrapy list
       - 展示爬虫应用列表
     
    4. scrapy crawl 爬虫应用名称<name>
       - 运行单独爬虫应用
    

      

    2.项目结构以及爬虫应用简介

    project_name/
       scrapy.cfg
       project_name/
           __init__.py
           items.py
           pipelines.py
           settings.py
           spiders/
               __init__.py
               爬虫1.py
               爬虫2.py
               爬虫3.py
    

      

    文件说明:

    • scrapy.cfg  项目的主配置信息。(真正爬虫相关的配置信息在settings.py文件中)
    • items.py    设置数据存储模板,用于结构化数据,如:Django的Model
    • pipelines    数据处理行为,如:一般结构化的数据持久化
    • settings.py 配置文件,如:递归的层数、并发数,延迟下载等
    • spiders      爬虫目录,如:创建文件,编写爬虫规则

    爬虫文件

      

    import scrapy
    from scrapy.http.request import Request
    from pacong.items import PacongItem
    import time
    import json
    
    # from scrapy.dupefilter import RFPDupeFilter,request_fingerprint
    
    
    class ChoutiSpider(scrapy.Spider):
    	name = 'chouti'
    	allowed_domains = ['chouti.com']
    	start_urls = [
    		"https://dig.chouti.com/",
    	]
    
    	# 默认scrapy遵守robot协议,所以会先请求这个文件查看自己的权限,出错是因为使用的爬虫爬取内容违背这个robot.txt。所以只要让爬虫不遵守该协议就好了,
    	# 具体做法是找到settings文件里的ROBOTSTXT_OBEY设置成False。
    
    	# 回调函数;response响应对象
    	def parse(self, response):
    		# response.meta   --- > response.request.meta
    		from scrapy.http import Response
    		# self.request.meta
    		print("chouti",response)
    		# item = response.xpath('//div[@class="link-con"]')
    		# if not item:
    		# 	#点击加载更多后的数据
    		# 	ret = json.loads(response.text)
    		# 	for n_news in ret["data"]:
    		# 		print(n_news['title'])
    		# 		print(n_news['originalUrl'])
    		# #第一次
    		# data_id = item.xpath('./div/@data-id').extract()
    		# for id in data_id:
    		# 	new = response.xpath('//div[@class="link-con"]/div[@class="link-item clearfix link-item-{}"]'.format(id))
    		# 	href = new.xpath('.//a[@data-id="{}"]/@href'.format(id)).extract_first()
    		# 	title = new.xpath('.//a[@data-id="{}"]/text()'.format(id)).extract_first()
    		# 	print(href)
    			# yield PacongItem(title=title, path=href)
    			# 在spiders里面的py文件中,yield 一次 Item对象,就调用一次proces_item
    			# yield Request()对象  就会再一次发起请求,把请求给调度器,
    			# 然后下载器从调度器里面取任务,借助 twisted 去互联网下载网页,然后把响应返回给parse回调函数。
    

      

    windows编码问题

    import sys,os
    sys.stdout=io.TextIOWrapper(sys.stdout.buffer,encoding='gb18030')
    

      

    执行此爬虫文件,则在终端进入项目目录执行如下命令:     

    scrapy crawl chouti--nolog
    

    对于上述代码重要之处在于:

    • Request是一个封装用户请求的类,在回调函数中yield该对象表示继续访问
    • HtmlXpathSelector用于结构化HTML代码并提供选择器功能

    4. 选择器  

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from scrapy.selector import Selector, HtmlXPathSelector
    from scrapy.http import HtmlResponse
    html = """<!DOCTYPE html>
    <html>
        <head lang="en">
            <meta charset="UTF-8">
            <title></title>
        </head>
        <body>
            <ul>
                <li class="item-"><a id='i1' href="link.html">first item</a></li>
                <li class="item-0"><a id='i2' href="llink.html">first item</a></li>
                <li class="item-1"><a href="llink2.html">second item<span>vv</span></a></li>
            </ul>
            <div><a href="llink2.html">second item</a></div>
        </body>
    </html>
    """
    response = HtmlResponse(url='http://example.com', body=html,encoding='utf-8')
    # hxs = HtmlXPathSelector(response)
    # print(hxs)
    # hxs = Selector(response=response).xpath('//a')
    # print(hxs)
    # hxs = Selector(response=response).xpath('//a[2]')
    # print(hxs)
    # hxs = Selector(response=response).xpath('//a[@id]')
    # print(hxs)
    # hxs = Selector(response=response).xpath('//a[@id="i1"]')
    # print(hxs)
    # hxs = Selector(response=response).xpath('//a[@href="link.html"][@id="i1"]')
    # print(hxs)
    # hxs = Selector(response=response).xpath('//a[contains(@href, "link")]')
    # print(hxs)
    # hxs = Selector(response=response).xpath('//a[starts-with(@href, "link")]')
    # print(hxs)
    # hxs = Selector(response=response).xpath('//a[re:test(@id, "id+")]')
    # print(hxs)
    # hxs = Selector(response=response).xpath('//a[re:test(@id, "id+")]/text()').extract()
    # print(hxs)
    # hxs = Selector(response=response).xpath('//a[re:test(@id, "id+")]/@href').extract()
    # print(hxs)
    # hxs = Selector(response=response).xpath('/html/body/ul/li/a/@href').extract()
    # print(hxs)
    # hxs = Selector(response=response).xpath('//body/ul/li/a/@href').extract_first()
    # print(hxs)
     
    # ul_list = Selector(response=response).xpath('//body/ul/li')
    # for item in ul_list:
    #     v = item.xpath('./a/span')
    #     # 或
    #     # v = item.xpath('a/span')
    #     # 或
    #     # v = item.xpath('*/a/span')
    #     print(v)
    

    注意:settings.py中设置DEPTH_LIMIT = 1来指定“递归”的层数。  

    持久化 的步骤

    pipeline/items
    a. 先写pipeline类
    class XXXPipeline(object):
    def process_item(self, item, spider):
    return item

    b. 写Item类
    class XdbItem(scrapy.Item):
    href = scrapy.Field()
    title = scrapy.Field()

    c. 配置
    ITEM_PIPELINES = {
    'xdb.pipelines.XdbPipeline': 300,
    }

    d. 爬虫,yield每执行一次,process_item就调用一次。

    yield Item对象

    class PacongPipeline(object):
    
        def __init__(self,path):
            self.f = None
            self.path = path
    
        @classmethod
        def from_crawler(cls,crawler):
            '''
            初始化的时候,用于创建 pipeline 对象
            :param crawler:
            :return:
            '''
            # crawler.settings 可以拿到配置文件
            path = crawler.settings.get('HREF_FILE_PATH')
            # 返回这个类的对象的时候,就对应的执行这个类的__init__方法
            return cls(path)
    
        #开始爬虫前执行的
        def open_spider(self,spider):
            # self.f=open(self.path,'w')
            print("PacongPipeline",'open')
    
        #在spiders里面的py文件中,yield 一次 Item对象,就调用一次proces_item
        def process_item(self, item, spider):
            '''
            :param item:  就是  PacongItem
            :param spider: 就是 爬虫的这个类 ChoutiSpider
            :return:
            '''
            #pipeline是所有爬虫公用,
            #要想给特定的爬虫,就可以用spider.name来限制
            # if spider.name=='chouti':
            #     pass
            # print(item,type(item)) item 是一个类
            # if 'http' not in item['path'] or 'https'not in item['path']:
            #     item['path'] = 'https://dig.chouti.com' + item['path']
            #
            # self.f.write('新闻:'+item['title']+'
    '+'链接:'+item['path']+'
    ')
            print('PacongPipeline',item)
            return item
            #返回的 item 是交给下一个Pipeline里面的process_item方法里面的 item
        #结束爬虫后执行的
        def close_spider(self,spider):
            # self.f.close()
            print("PacongPipeline", 'colse')
    

    注意:pipeline是所有爬虫公用,如果想要给某个爬虫定制需要使用spider参数自己进行处理。  

    去重规则

    a. 编写类 
    			from scrapy.dupefilter import BaseDupeFilter
    			from scrapy.utils.request import request_fingerprint
    
    			class XdbDupeFilter(BaseDupeFilter):
    
    				def __init__(self):
    					self.visited_fd = set()
    
    				@classmethod
    				def from_settings(cls, settings):
    					return cls()
    
    				def request_seen(self, request):
    					#request_fingerprint 类似将url转换为md5值;  
    					#www.123.com?k=2&n=2;n=2&k=2     优点能判断条件 是一样的
    					fd = request_fingerprint(request=request)
    					if fd in self.visited_fd:
    						return True
    					self.visited_fd.add(fd)
    
    				def open(self):  # can return deferred
    					print('开始')
    
    				def close(self, reason):  # can return a deferred
    					print('结束')
    
    				# def log(self, request, spider):  # log that a request has been filtered
    				#     print('日志')
    
    		b. 配置 
    			# 修改默认的去重规则
    			# DUPEFILTER_CLASS = 'scrapy.dupefilter.RFPDupeFilter'
    			DUPEFILTER_CLASS = 'xdb.dupefilters.XdbDupeFilter'
    
    
    		c. 爬虫使用:
    			class ChoutiSpider(scrapy.Spider):
    				name = 'chouti'
    				allowed_domains = ['chouti.com']
    				start_urls = ['https://dig.chouti.com/']
    
    				def parse(self, response):
    					print(response.request.url)
    					# item_list = response.xpath('//div[@id="content-list"]/div[@class="item"]')
    					# for item in item_list:
    					#     text = item.xpath('.//a/text()').extract_first()
    					#     href = item.xpath('.//a/@href').extract_first()
    
    					page_list = response.xpath('//div[@id="dig_lcpage"]//a/@href').extract()
    					for page in page_list:
    						from scrapy.http import Request
    						page = "https://dig.chouti.com" + page
    						yield Request(url=page,callback=self.parse,dont_filter=False) 
    

    cookie 

    在发送请求时cookie的操作,
    meta={'cookiejar':1}表示开启cookie记录,首次请求时写在Request()里
    meta={'cookiejar':response.meta['cookiejar']}表示使用上一次response的cookie,写在FormRequest.from_response()里post授权
    meta={'cookiejar':True}表示使用授权后的cookie访问需要登录查看的页面

    获取Scrapy框架Cookies

    请求Cookie
    Cookie = response.request.headers.getlist('Cookie')

    响应Cookie
    Cookie2 = response.headers.getlist('Set-Cookie')

    # -*- coding: utf-8 -*-
    import scrapy
    from scrapy.http import Request,FormRequest
    
    class PachSpider(scrapy.Spider):                            #定义爬虫类,必须继承scrapy.Spider
        name = 'pach'                                           #设置爬虫名称
        allowed_domains = ['edu.iqianyue.com']                  #爬取域名
        # start_urls = ['http://edu.iqianyue.com/index_user_login.html']     #爬取网址,只适于不需要登录的请求,因为没法设置cookie等信息
    
        header = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0'}  #设置浏览器用户代理
    
        def start_requests(self):       #用start_requests()方法,代替start_urls
            """第一次请求一下登录页面,设置开启cookie使其得到cookie,设置回调函数"""
            return [Request('http://edu.iqianyue.com/index_user_login.html',meta={'cookiejar':1},callback=self.parse)]
    
        def parse(self, response):     #parse回调函数
    
            data = {                    #设置用户登录信息,对应抓包得到字段
                'number':'adc8868',
                'passwd':'279819',
                'submit':''
                }
    
            # 响应Cookie
            Cookie1 = response.headers.getlist('Set-Cookie')   #查看一下响应Cookie,也就是第一次访问注册页面时后台写入浏览器的Cookie
            print(Cookie1)
    
            print('登录中')
            """第二次用表单post请求,携带Cookie、浏览器代理、用户登录信息,进行登录给Cookie授权"""
            return [FormRequest.from_response(response,
                                              url='http://edu.iqianyue.com/index_user_login',   #真实post地址
                                              meta={'cookiejar':response.meta['cookiejar']},
                                              headers=self.header,
                                              formdata=data,
                                              callback=self.next,
                                              )]
        def next(self,response):
            a = response.body.decode("utf-8")   #登录后可以查看一下登录响应信息
            # print(a)
            """登录后请求需要登录才能查看的页面,如个人中心,携带授权后的Cookie请求"""
            yield Request('http://edu.iqianyue.com/index_user_index.html',meta={'cookiejar':True},callback=self.next2)
        def next2(self,response):
            # 请求Cookie
            Cookie2 = response.request.headers.getlist('Cookie')
            print(Cookie2)
    
            body = response.body  # 获取网页内容字节类型
            unicode_body = response.body_as_unicode()  # 获取网站内容字符串类型
    
            a = response.xpath('/html/head/title/text()').extract()  #得到个人中心页面
            print(a)
    

      

    参考https://blog.csdn.net/hoddy355/article/details/80779498 

    解析cookie

    cookie_jar = CookieJar()
            cookie_jar.extract_cookies(response, response.request)
            for k, v in cookie_jar._cookies.items():
          # 去对象中将cookie解析到字典 for i, j in v.items(): for m, n in j.items(): self.cookie_dict[m] = n.value

      

    抽屉利用cookie点赞

    # -*- coding: utf-8 -*-
    import scrapy
    from scrapy.selector import HtmlXPathSelector
    from scrapy.http.request import Request
    from scrapy.http.cookies import CookieJar
    from scrapy import FormRequest
    
    
    class ChouTiSpider(scrapy.Spider):
        # 爬虫应用的名称,通过此名称启动爬虫命令
        name = "chouti"
        # 允许的域名
        allowed_domains = ["chouti.com"]
    
        cookie_dict = {}
        has_request_set = {}
    
        def start_requests(self):
            url = 'http://dig.chouti.com/'
            # return [Request(url=url, callback=self.login)]
            yield Request(url=url, callback=self.login)
    
        def login(self, response):
            cookie_jar = CookieJar()
            cookie_jar.extract_cookies(response, response.request)
            for k, v in cookie_jar._cookies.items():
                for i, j in v.items():
                    for m, n in j.items():
                        self.cookie_dict[m] = n.value
    
            req = Request(
                url='http://dig.chouti.com/login',
                method='POST',
                headers={'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
                body='phone=8615131255089&password=pppppppp&oneMonth=1',
                cookies=self.cookie_dict,
                callback=self.check_login
            )
            yield req
    
        def check_login(self, response):
            req = Request(
                url='http://dig.chouti.com/',
                method='GET',
                callback=self.show,
                cookies=self.cookie_dict,
                dont_filter=True
            )
            yield req
    
        def show(self, response):
            # print(response)
            hxs = HtmlXPathSelector(response)
            news_list = hxs.select('//div[@id="content-list"]/div[@class="item"]')
            for new in news_list:
                # temp = new.xpath('div/div[@class="part2"]/@share-linkid').extract()
                link_id = new.xpath('*/div[@class="part2"]/@share-linkid').extract_first()
                yield Request(
                    url='http://dig.chouti.com/link/vote?linksId=%s' %(link_id,),
                    method='POST',
                    cookies=self.cookie_dict,
                    callback=self.do_favor
                )
    
            page_list = hxs.select('//div[@id="dig_lcpage"]//a[re:test(@href, "/all/hot/recent/d+")]/@href').extract()
            for page in page_list:
    
                page_url = 'http://dig.chouti.com%s' % page
                import hashlib
                hash = hashlib.md5()
                hash.update(bytes(page_url,encoding='utf-8'))
                key = hash.hexdigest()
                if key in self.has_request_set:
                    pass
                else:
                    self.has_request_set[key] = page_url
                    yield Request(
                        url=page_url,
                        method='GET',
                        callback=self.show
                    )
    
        def do_favor(self, response):
            print(response.text)
    
    示例:自动登陆抽屉并点赞
    

    中间件  

    #爬虫中间件(对深度和优先级的操作)
    #下载中间件(对请求进行加工或者是加代理)
    class SpiderMiddleware(object):
    
        def process_spider_input(self,response, spider):
            """
            下载完成,执行,然后交给parse处理
            :param response: 
            :param spider: 
            :return: 
            """
            pass
    
        def process_spider_output(self,response, result, spider):
            """
            spider处理完成,返回时调用
            :param response:
            :param result:
            :param spider:
            :return: 必须返回包含 Request 或 Item 对象的可迭代对象(iterable)
            """
            return result
    
        def process_spider_exception(self,response, exception, spider):
            """
            异常调用
            :param response:
            :param exception:
            :param spider:
            :return: None,继续交给后续中间件处理异常;含 Response 或 Item 的可迭代对象(iterable),交给调度器或pipeline
            """
            return None
    
    
        def process_start_requests(self,start_requests, spider):
            """
            爬虫启动时调用
            :param start_requests:
            :param spider:
            :return: 包含 Request 对象的可迭代对象
            """
            return start_requests
    
    爬虫中间件
    
    class DownMiddleware1(object):
        def process_request(self, request, spider):
            """
            请求需要被下载时,经过所有下载器中间件的process_request调用
            :param request: 
            :param spider: 
            :return:  
                None,继续后续中间件去下载;
                Response对象,停止process_request的执行,开始执行process_response
                Request对象,停止中间件的执行,将Request重新调度器
                raise IgnoreRequest异常,停止process_request的执行,开始执行process_exception
            """
            pass
    
    
    
        def process_response(self, request, response, spider):
            """
            spider处理完成,返回时调用
            :param response:
            :param result:
            :param spider:
            :return: 
                Response 对象:转交给其他中间件process_response
                Request 对象:停止中间件,request会被重新调度下载
                raise IgnoreRequest 异常:调用Request.errback
            """
            print('response1')
            return response
    
        def process_exception(self, request, exception, spider):
            """
            当下载处理器(download handler)或 process_request() (下载中间件)抛出异常
            :param response:
            :param exception:
            :param spider:
            :return: 
                None:继续交给后续中间件处理异常;
                Response对象:停止后续process_exception方法
                Request对象:停止中间件,request将会被重新调用下载
            """
            return None
    
    下载器中间件
    

     下载中间件

    爬虫中间件

    在下载中间件加代理

    下载中间件
    - scrapy中设置代理 
    	- 内置
    		在爬虫启动时,提前在os.envrion中设置代理即可。
    		    class ChoutiSpider(scrapy.Spider):
    				name = 'chouti'
    				allowed_domains = ['chouti.com']
    				start_urls = ['https://dig.chouti.com/']
    				cookie_dict = {}
    
    				def start_requests(self):
    					import os
    					os.environ['HTTPS_PROXY'] = "http://root:woshiniba@192.168.11.11:9999/"
    					os.environ['HTTP_PROXY'] = '19.11.2.32',
    					for url in self.start_urls:
    						yield Request(url=url,callback=self.parse)
    		meta:
    			class ChoutiSpider(scrapy.Spider):
    				name = 'chouti'
    				allowed_domains = ['chouti.com']
    				start_urls = ['https://dig.chouti.com/']
    				cookie_dict = {}
    
    				def start_requests(self):
    					for url in self.start_urls:
    						yield Request(url=url,callback=self.parse,meta={'proxy':'"http://root:woshiniba@192.168.11.11:9999/"'})
    
    	- 自定义
    		# by luffycity.com
    		import base64
    		import random
    		from six.moves.urllib.parse import unquote
    		try:
    			from urllib2 import _parse_proxy
    		except ImportError:
    			from urllib.request import _parse_proxy
    		from six.moves.urllib.parse import urlunparse
    		from scrapy.utils.python import to_bytes
    
    		class XdbProxyMiddleware(object):
    
    			def _basic_auth_header(self, username, password):
    				user_pass = to_bytes(
    					'%s:%s' % (unquote(username), unquote(password)),
    					encoding='latin-1')
    				return base64.b64encode(user_pass).strip()
    			#按照原码来写。				
    			def process_request(self, request, spider):
    				PROXIES = [
    					"http://root:woshiniba@192.168.11.11:9999/",
    					"http://root:woshiniba@192.168.11.12:9999/",
    					"http://root:woshiniba@192.168.11.13:9999/",
    					"http://root:woshiniba@192.168.11.14:9999/",
    					"http://root:woshiniba@192.168.11.15:9999/",
    					"http://root:woshiniba@192.168.11.16:9999/",
    				]
    				url = random.choice(PROXIES)
    
    				orig_type = ""
    				proxy_type, user, password, hostport = _parse_proxy(url)
    				proxy_url = urlunparse((proxy_type or orig_type, hostport, '', '', '', ''))
    
    				if user:
    					creds = self._basic_auth_header(user, password)
    				else:
    					creds = None
    				request.meta['proxy'] = proxy_url
    				if creds:
    					request.headers['Proxy-Authorization'] = b'Basic ' + creds
    

      

     

    自定制命令  

    有以下步骤:

    • 在spiders同级创建任意目录,如:commands
    • 在其中创建 crawlall.py 文件 (此处文件名就是自定义的命令)
    • from scrapy.commands import ScrapyCommand
          from scrapy.utils.project import get_project_settings
      
      
          class Command(ScrapyCommand):
      
              requires_project = True
      
              def syntax(self):
                  return '[options]'
      
              def short_desc(self):
                  return 'Runs all of the spiders'
      
              def run(self, args, opts):
                  spider_list = self.crawler_process.spiders.list()
                  for name in spider_list:
                      self.crawler_process.crawl(name, **opts.__dict__)
                  self.crawler_process.start()
      
      crawlall.py
      
    • 在settings.py 中添加配置 COMMANDS_MODULE = '项目名称.目录名称'
    • 在项目目录执行命令:scrapy crawlall 
    import sys
    from scrapy.cmdline import execute
    
    if __name__ == '__main__':
        execute(["scrapy","github","--nolog"])
    

    自定义扩展

    自定义扩展时,利用信号在指定位置注册制定操作

    用scrapy的信号,可以在爬虫前和爬虫后等定制一些操作

    from scrapy import signals
    #看源码可以看到所有的信号。
    
    class MyExtension(object):
        def __init__(self, value):
            self.value = value
    
        @classmethod
        def from_crawler(cls, crawler):
            val = crawler.settings.getint('MMMM')
            ext = cls(val)
    
            crawler.signals.connect(ext.spider_opened, signal=signals.spider_opened)
            crawler.signals.connect(ext.spider_closed, signal=signals.spider_closed)
    
            return ext
    
        def spider_opened(self, spider):
            print('open')
    
        def spider_closed(self, spider):
            print('close')
    ext = MyExtension() 
    配置:
    EXTENSIONS = {'xdb.ext.MyExtend':666,}
    

      

    更多详情  点击

  • 相关阅读:
    C++计时器:毫秒级和微秒级
    28款GitHub最流行的开源机器学习项目
    图像旋转公式 旋转中心点
    JNA
    this
    Random Javascript code snippets
    type
    TreeView的异步延时加载
    C#递归所以部门展示到TreeView
    C#判断是否是节假日
  • 原文地址:https://www.cnblogs.com/zenghui-python/p/11653528.html
Copyright © 2011-2022 走看看