zoukankan      html  css  js  c++  java
  • Python Scrapy框架

    1. scrapy安装与环境依赖

    # 1.在安装scrapy前需要安装好相应的依赖库, 再安装scrapy, 具体安装步骤如下: 
    (1).安装lxml库: pip install lxml 
    (2).安装wheel: pip install wheel 
    (3).安装twisted: pip install twisted文件路径 
        ***根据网址进入页面后,找到跟自己电脑相匹配的安装包下载,下载成功后,复制到一个文件夹在地址栏用cmd打开切换到python环境中执行命令  twisted: pip install twisted文件路径(T+tab键会自动生成)
    	(twisted需下载后本地安装,下载地 址:http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted) 	  	  (版本选择如下图,版本后面有解释,请根据自己实际选择) 
    (4).安装pywin32: pip install pywin32 
         (注意:以上安装步骤一定要确保每一步安装都成功,没有报错信息,如有报错自行百度解决) 
    (5).安装scrapy: pip install scrapy 
         (注意:以上安装步骤一定要确保每一步安装都成功,没有报错信息,如有报错自行百度解决) 
    (6).成功验证:在cmd命令行输入scrapy,显示Scrapy1.6.0-no active project,证明安装成功
    

    2. 创建项目等--命令介绍

    # 1.手动创建一个目录test 
    # 2.在test文件夹下创建爬虫项目为spiderpro: *(命令)scrapy startproject spiderpro(项目名称) *
    # 3.进入项目文件夹: cd spiderpro 
    # 4.创建爬虫文件: scrapy genspider 爬虫名 域名(www.baidu.com---意思只能爬取在百度以内的东西)
    # 5.启动scrapy的命令:scrapy crawl +'爬虫名'
    # 6.解析方法 extract_first()--->目标数据,如果拼错了,不飘红也不报错,就是拿不到数据。
    # 7.当在scrapy的框架中,获取列表数据的一条用---extract_first()
    # 8.当在scrapy的框架中,获取列表的所有数据用---extract()
    

    3. 项目目录介绍

    spiderpro 
    	spiderpro # 项目目录 
    	__init__ 
    	spiders:爬虫文件目录 
    		__init__ 
    		tests.py:爬虫文件 
    	items.py:定义爬取数据持久化的数据结构 
    	middlewares.py:定义中间件 
    	pipelines.py:管道,持久化存储相关 
    	settings.py:配置文件 
    venv:虚拟环境目录 
    scrapy.cfg: scrapy 项目部署有关
        
    #说明: 
        1).spiders:其内包含一个个Spider的实现, 每个Spider是一个单独的文件 
        2).items.py:它
        定义了Item数据结构, 爬取到的数据存储为哪些字段 
        3).pipelines.py:它定义Item Pipeline的实现
        4).settings.py:项目的全局配置 
        5).middlewares.py:定义中间件, 包括爬虫中间件和下载中间
        件 
        6).scrapy.cfg:它是scrapy项目的配置文件, 其内定义了项目的配置路径, 部署相关的信息等
    

    4. 框架scrapy介绍:五大核心组件与数据流向

    # 架构: 
    1).Scrapy Engine: 这是引擎,负责Spiders、ItemPipeline、Downloader、Scheduler中间的通 讯,信号、数据传递等等! 
    2).Scheduler(调度器): 它负责接受引擎发送过来的requests请求,并按照一定的方式进行整理排列, 入队、并等待Scrapy Engine(引擎)来请求时,交给引擎。 
    3).Downloader(下载器):负责下载Scrapy Engine(引擎)发送的所有Requests请求,并将其获取到 的Responses交还给Scrapy Engine(引擎),由引擎交给Spiders来处理,
    4).Spiders:它负责处理所有Responses,从中分析提取数据,获取Item字段需要的数据,并将需要跟进 的URL提交给引擎,再次进入Scheduler(调度器), 
    5).Item Pipeline:它负责处理Spiders中获取到的Item,并进行处理,比如去重,持久化存储(存数据 库,写入文件,总之就是保存数据用的) 
    6).Downloader Middlewares(下载中间件):你可以当作是一个可以自定义扩展下载功能的组件 
    7).Spider Middlewares(Spider中间件):你可以理解为是一个可以自定扩展和操作引擎和Spiders中 间‘通信‘的功能组件(比如进入Spiders的Responses;和从Spiders出去的Requests)
    
    
    # 工作流: 
    spider --> 引擎 --> 调度器 --> 引擎 --> 下载器 --> 引擎 --> spider --> 引擎 --> 管道 --> 数据库
        1).spider将请求发送给引擎, 引擎将request发送给调度器进行请求调度 
        2).调度器把接下来要请求的request发送给引擎, 引擎传递给下载器, 中间会途径下载中间件 
        3).下载携带request访问服务器, 并将爬取内容response返回给引擎, 引擎将response返回给 spider 
        4).spider将response传递给自己的parse进行数据解析处理及构建item一系列的工作, 最后将item 返回给引擎, 引擎传递个pipeline 	
        5).pipe获取到item后进行数据持久化 
        6).以上过程不断循环直至爬虫程序终止
        
        #__init__初始化方法   __new__()  构造方法 :当spider接收到res响应后定义类,实例化对象存到属性中也就是存在内存上,下一步才准备存到数据库
    

    5. scrapy--爬取科客网站

    # 1. itmes.py 里配置想要抓取的字段(想要抓取多少内容)
    
    # -*- coding: utf-8 -*-
    
    # Define here the models for your scraped items
    #
    # See documentation in:
    # https://docs.scrapy.org/en/latest/topics/items.html
    
    import scrapy
    # 所写的字段
    class ProItem(scrapy.Item):
        # define the fields for your item here like:
        img = scrapy.Field()    ******
        title = scrapy.Field()  ******
        image_url = scrapy.Field()   *****所需代码
    
        
    # 2. 在自己定义的爬虫py文件中
    # 定义了爬取数据的行为, 定义了数据解析的规则
    import scrapy
    #  将解析好的数据需要需要实例化存在一个属性中
    from ..items import ProItem
    class MyproSpider(scrapy.Spider):
        name = 'mypro'    # 爬虫名, 启动项目时用
        # allowed_domains = ['www.baidu.com']   # # 定义了爬取的范围 ,可注释掉,如果不注释则影响爬虫效果
        start_urls = ['http://www.keke289.com/']     ## 起始url, 项目启动时, 会自动向起始url发起请求
    	#解析方法
        def parse(self, response):
            #用response响应进行数据解析--》xpath解析的并不是一个真实的列表
            div_list = response.xpath('//article[contains(@class,"article")]')
            for i in div_list:
                title = i.xpath('./div/h2/a/text()').extract_first()
                href = i.xpath('./div/h2/a/@href').extract_first()
                src = i.xpath('./div/a/img/@lazy_src').extract_first()
                #实例化对象
                item = ProItem()
                #将解析的数据找其相对应的字段进行赋值----存储到item属性中(字典)
                item['title'] = title
                item['image_url'] = href
                item['img'] = src
                # yield 将数据发送给管道Pipelines
                yield item
               
            
    # 3.在pipelines.py 里进行MongoDB存储
    # 导入pymongo模块
    import pymongo
    class ProPipeline(object):
        def process_item(self, item, spider):
            # python 与 MongoDB 数据库交互
            conn = pymongo.MongoClient('localhost',27017)
            # 创建或连接库
            db = conn.keke
            # 创建或连接表
            table = db.kuke
            table.insert_one(dict(item))
            return item
        
        
    # 4. 在settinds.py 里修改所需要的配置
    # 此示例中配置文件中的配置的项, 注意是不是全部的配置, 是针对该项目增加或修改的配置项 
    # 忽略robots协议 -----》把True改成False(代表不遵守协议)
    ROBOTSTXT_OBEY =False 
    # UA伪装 ----》换成自己的 UA
    USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.87 Safari/537.36' 
    # 管道类打开以防数据发送不过来 --->把注释解掉即可
    ITEM_PIPELINES ={ 'qsbk.pipelines.QsbkPipeline':300, }
    
    

    6. scrapy实现多页爬取

    1). #在起始url中,输入有顺序的每页地址,然后格式化输出。
    例:
    start_urls = ['http://www.009renti.com/evarenti/RenTiCaiHui/14_%s.html' % for i in range(1,3)]
    
    
    2). # spider编码在原基础之上, 构建其他页面的url地址, 并利用scrapy.Request发起新的请求, 请求的 回调函数依然是parse: 
    #声明page页码数为第一页
    page = 1 
    base_url = 'http://www.xiaohuar.com/list-1-%s.html' 
    # 爬取一共四页的数据所以小于4,因为每次self.page+1,当到第三页时依次加一所以就四页了,要几页写几页
    if self.page < 4: 
        #格式化拼接页码数
        page_url = base_url%self.page 
        #依次加一
        self.page += 1 
        #爬取多页收据,将yield函数里  用scrapy.Request再次请求,callback回调其自身函数就OK
        yield scrapy.Request(url=page_url, callback=self.parse) 
        # (其他文件不用改动)
       
    ####  准确使用
    import scrapy
    from ..items import BizhiItem
    class MybizhiSpider(scrapy.Spider):
        name = 'mybizhi'
        # allowed_domains = ['www.baidu.com']
        1).# start_urls = ['http://sj.zol.com.cn/bizhi/mingxing/%s.html'% i for i in range(1,5)]
        2). #定义起始url为第一页数据
        start_urls = ['http://sj.zol.com.cn/bizhi/mingxing/1.html']
        #定义page=1从第一页开始
        page = 1
        def parse(self, response):
            div_list = response.xpath('//li[@class="photo-list-padding"]')
            for div in div_list:
                title = div.xpath('./a/span/em/text()').extract_first()
                image_url = div.xpath('./a/img/@src').extract_first()
                detail_url = div.xpath('./a/@href').extract_first()
                item = BizhiItem()
                item['title'] = title
                item['image_url'] = image_url
                item['detail_url'] = detail_url
                # 输入爬取多少页的数据
                if self.page < 4:
                    #每次加一页,直到全部爬取结束
                    self.page += 1
                    #将每页拼接到页码上
                    url = 'http://sj.zol.com.cn/bizhi/mingxing/%s.html'%self.page
                    #再次请求,调用自身函数
                    yield scrapy.Request(url=url,callback=self.parse)
                #最后将数据发送到管道,存入MongoDB
                yield item
    

    7. scrapy解析笑话网站例

    import scrapy
    from ..items import SkillItem
    
    class MyskillSpider(scrapy.Spider):
        name = 'myskill'
        # allowed_domains = ['www.baidu.com']
        start_urls = ['http://www.jokeji.cn/?bmjmxa=ziqzh']
    	#自己定义的函数
        def detail_parse(self, response):
            # 将回调传来的值,取出
            item = response.meta['item']
            *****
            当在scrapy的框架中,获取列表数据的一条用---extract_first()
            当在scrapy的框架中,获取列表的所有数据用---extract()
            *****
            detail_url = response.xpath('//span[@id="text110"]/p/text()').extract()
            # 解析的目标数据是一个大字典用  '' .join()拼接使其变成字符串
            item['detail_url'] = ''.join(detail_url)
            # 最后在发送到管道
            yield item
    
        def parse(self, response):
            div_list = response.xpath('//div[@class="newcontent l_left"]/ul/li')
            for div in div_list:
                title = div.xpath('./a/text()').extract_first()
                link = div.xpath('./a/@href').extract_first()
                item = SkillItem()
                item['title'] = title
                item['link'] = 'http://www.jokeji.cn'+link
                # 爬取网页xpath解析,实例化对象将其相对应的字段进行赋值,获取详情页连接再次发起去请求,
                # 用yield的SCRAPY.Request的内置参数callback回调一个函数,meta将值传送到回调函数
                yield scrapy.Request(url='http://www.jokeji.cn'+link,callback=self.detail_parse,meta={'item':item})
    

    8. scrapy框架下载图片代码

    
    1).item.py定义字段赋值
    
    import scrapy
    class BizhiItem(scrapy.Item):
        # 定义需要的字段与爬虫文件相关联
        title = scrapy.Field()
        image_url = scrapy.Field()
        detail_url = scrapy.Field()
        
    2). 爬虫py文件
    
    import scrapy
    # 导入item的类名内容
    from ..items import BizhiItem
    class MybizhiSpider(scrapy.Spider):
        name = 'mybizhi'
        # allowed_domains = ['www.baidu.com']
        # start_urls = ['http://sj.zol.com.cn/bizhi/mingxing/%s.html'% i for i in range(1,5)]
        start_urls = ['http://sj.zol.com.cn/bizhi/mingxing/1.html']
        def pic_parse(self, response):
            #接收传送的参数取出来
            item = response.meta['item']
            #图片的名字按照 / 切割
            name = item['image_url'].split('/')[-1]
            # 响应内容,获取图片的二进制流
            content = response.body
            # open 打开的文件,***************imgs文件(图片存储的文件)一定要跟scrapy.cfg平级,不然拿不到***********
            with open('./imgs/%s'%name,'wb') as f:
                #把二进制流写入
                f.write(content)
                # 逻辑工作结束后,最后将item发送至管道
                yield item
    
        def parse(self, response):
            div_list = response.xpath('//li[@class="photo-list-padding"]')
            for div in div_list:
                title = div.xpath('./a/span/em/text()').extract_first()
                image_url = div.xpath('./a/img/@src').extract_first()
                detail_url = div.xpath('./a/@href').extract_first()
                item = BizhiItem()
                item['title'] = title
                item['image_url'] = image_url
                item['detail_url'] = detail_url
                # 再次请求一个图片地址链接,把赋值好的属性传送过去。
                yield scrapy.Request(url=image_url,callback=self.pic_parse,meta={'item':item}) 
                
    3).piplines.py 管道py存数据
    import pymongo
    
    class BizhiPipeline(object):
        def process_item(self, item, spider):
            # 与MongoDB数据库交互   域名加端口
            conn = pymongo.MongoClient('localhost',27017)
            # 创建数据库或者连接数据库
            db = conn.xxxxx
            # 创建表或者连接表
            table = db.yyyyy
            # 插入数据
            table.insert_one(dict(item))
            return item
    
         
    4).settings.py配置内容
    # 此示例中配置文件中的配置的项, 注意是不是全部的配置, 是针对该项目增加或修改的配置项 
    # 忽略robots协议 -----》把True改成False(代表不遵守协议)
    ROBOTSTXT_OBEY =False 
    # UA伪装 ----》换成自己的 UA
    USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.87 Safari/537.36' 
    # 管道类打开以防数据发送不过来 --->把注释解掉即可
    ITEM_PIPELINES ={ 'qsbk.pipelines.QsbkPipeline':300, }
    

    9. scrapy 篡改请求与响应,item丢弃

    1).-- UA池--->大量UA----->拦截请求  ---->换UA 
    2).-- IP代理池---->请求---->换IP
    3).-- cookie池---->换cookie
    4).-- 拦截响应(动态加载)--selenium抓取(res.scrapy<---->res.selenium)--给引擎--->spider
    

    10. scrapy中间件--分类,作用

    # 中间件分类
    	- 下载中间键:DownloadMiddleware
        - 爬虫中间件:SpiderMiddleware
    
    # 中间件的作用
    	- 下载中间件: 拦截请求与响应, 篡改请求与响应 
        - 爬虫中间件: 拦截请求与响应, 拦截管道item, 篡改请求与响应, 处理item
    
    # 下载中间件的主要方法: 
    process_request     #获取拦截非异常请求
    process_response    #获取拦截所有响应
    process_exception   #获取拦截异常请求
    

    11. 下载中间件拦截请求, 使用代理ip案例

    1).# spider编码: 
    import scrapy 
    class DlproxySpider(scrapy.Spider): 
    	name = 'dlproxy' 
    	# allowed_domains = ['www.baidu.com'] 
    	start_urls = ['https://www.baidu.com/s?wd=ip']
    def parse(self, response): 
    	with open('baiduproxy.html', 'w', encoding='utf-8') as f: 
    		f.write(response.text)
            
    2).# Downloadermiddleware编码: 
    def process_request(self, request, spider): 
        # http://www.goubanjia.com
        request.meta['proxy'] = 'http://111.231.90.122:8888' 
        return None
    
    3).# settings编码
    USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'
    ROBOTSTXT_OBEY = False
    # 把下载中间件注释打开
    Downloader_MIDDLEWARES = {
       'proxy.middlewares.ProxySpiderMiddleware': 543,
    }
    

    12. 下载中间件实现UA池

    1). 在middlewares.py
    from scrapy import signals
    # ua导包需下载 pip install fake-useragent
    
    from fake_useragent import UserAgent
    #导入随机
    import random
    #实例化
    ua_chrome = UserAgent()
    #定义ua池
    ua_pool = []
    for i in range(10):
        ua = ua_chrome.Chrome
        ua_pool.append(ua)
        
        # 拦截请求:拦截非异常的请求
        def process_request(self, request, spider):
            # request.meta['proxy'] = 'http://60.217.64.237:38829'
            request.headers['User-Agent'] = random.choice(ua_pool)
            return None
        # 拦截响应:拦截的是所有响应
        def process_response(self, request, response, spider):
            print('*'*50)
            ***** request.headers['User-Agent'] *****取ua
            print(request.headers['User-Agent'])
            print('*'*50)
            return response
       
    2).  需要注释的地方,跟修改的地方  在settings.py 里设置
    1.USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'
    2.ROBOTSTXT_OBEY = False
    #把下载中间件注释开
    3.DOWNLOADER_MIDDLEWARES = {
       'proxy.middlewares.ProxyDownloaderMiddleware': 543,
    }
    
    3). #在起始url里,用列表推导式里面加入for循环,依次循环就可以在ua池里任意获取
    start_urls = ['https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=ip&rsv_pq=cf95e45f000b8d2b&rsv_t=74b1V5e7UWXPDK6YWqzjFSXv%2B9wpMSDHZrF4HMP0TnouyBZ4o6hj%2FuiRWgI&rqlang=cn&rsv_enter=1&rsv_dl=tb&rsv_sug3=2&rsv_sug1=1&rsv_sug7=100&rsv_sug2=0&inputT=1452&rsv_sug4=1453' for i in range(3)]
    
    *************************************************************
    简单的UA池
    from fake_useragent import UserAgent
    for i in range(10):
        USER_AGENT = UserAgent().random
        print(USER_AGENT)
    *************************************************************
    

    13. selenium与scrapy框架对接

    1).item.py里
    # 定义爬取的字段
    import scrapy
    class NewsItem(scrapy.Item):
        title = scrapy.Field()
        image_url = scrapy.Field()
        
    *****************************************************************************************
    2).在爬虫的py里
    import scrapy
    from ..items import NewsItem
    from selenium import webdriver
    class MynewsSpider(scrapy.Spider):
        name = 'mynews'
        # allowed_domains = ['www.baidu.com']
        # 在起始的url里定义网址爬取的范围
        start_urls = ['https://news.163.com/domestic/']
        # 实例化selenium对象,executable_path=‘驱动程序的工具路径’
        browser = webdriver.Chrome(executable_path=r'D:爬虫段位day13
    ewschromedriver.exe')
    
        def image_parse(self, response):
            item = response.meta['item']
            content = response.body
            name = item['image_url'].split('/')[-1].split('?')[0]
            with open('./imgs/%s'% name,'wb') as f:
                f.write(content)
                yield item
    
        def parse(self, response):
            # 正常的xpath解析
            div_list = response.xpath('//div[contains(@class,"news_article")]')
            for div in div_list:
                title = div.xpath('./div/div/h3/a/text()').extract_first()
                image_url = div.xpath('./a/img/@src').extract_first()
                item = NewsItem()
                item['title'] = title
                item['image_url'] = image_url
                yield scrapy.Request(url=image_url,callback=self.image_parse,meta={'item':item})
    
    *****************************************************************************************            
    3).pipelines.py里 存数据
    import pymongo
    
    class NewsPipeline(object):
        def process_item(self, item, spider):
            conn = pymongo.MongoClient('localhost',27017)
            db = conn.news
            table = db.wynews
            table.insert_one(dict(item))
            return item
        
    ***************************************************************************************** 
    4).middlewares.py里
    from scrapy import signals
    from scrapy.http import HtmlResponse
    # 因为获取js的动态数据所以属于响应拦截
        def process_response(self, request, response, spider):
            # 在爬虫py里已导入自动化工具,用spider导进来运用
            browser = spider.browser
            # 在第一次请求的js动态数据,判断拦截后的响应的url在不在起始url里
            #   注意爬取的连接, 必要时判断
            if response.url in spider.start_urls:
                # 用自动化工具进行请求页面
                browser.get(request.url)
                # js下拉框 下拉一次
                js = 'window.scrollTo(0,document.body.scrollHeight)'
                # 把js 代码放入 browser.execute_script(js)
                browser.execute_script(js)
                # 获取响应后的页面赋给变量
                html = browser.page_source
                # 将拦截后获取的数据在发送给爬虫文件解析----
                # 固定参数 url=browser.current_url(currnet_url代表当前请求的url),body=html(body请求体),
                # encoding='utf-8'(文本编码),request=request(伪装成请求头,返回爬虫网页))
    
                return HtmlResponse(url=browser.current_url,body=html,encoding='utf-8',request=request)
            return response
        
    *****************************************************************************************
    5).settings.py设置
    USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'
    ROBOTSTXT_OBEY = False
    DOWNLOADER_MIDDLEWARES = {
       'news.middlewares.NewsDownloaderMiddleware': 543,
    }
    ITEM_PIPELINES = {
       'news.pipelines.NewsPipeline': 300,
    }
    

    14. scrapy 持久化与MongoDB交互

    # 核心方法讲解: 
    open_spider(self, spider): spider开启是被调用 close_spider(self, spider): spider关闭是被调用 from_crawler(cls, crawler): 类方法, 用@classmethod标识, 可以获取配置信息 
    Process_item(self, item, spider): 与数据库交互存储数据, 该方法必须实现 
    ***** # 重点: 所有的方法名都必须一致
    
    1). #在管道pipelines.py
    import pymongo
    class XiaoxiaoPipeline(object):
        # 初始化方法, __new__: 构造方法, 在内存中开辟一块空间
        def __init__(self,mongo_uri,mongo_db):
            self.mongo_uri = mongo_uri
            self.mongo_db = mongo_db
    
        def open_spider(self,spider):
            self.client = pymongo.MongoClient(self.mongo_uri)
            self.db = self.client[self.mongo_db]
    
        @classmethod
        # 调用配置中定义的方法
        def from_crawler(cls,crawler):
            return cls(
                mongo_uri = crawler.settings.get('MONGO_URI'),
                mongo_db = crawler.settings.get('MONGO_DB')
            )
    
    
        def process_item(self, item, spider):
            self.db['myxiao'].insert(dict(item))
            return item
    
        def close_spider(self,spider):
            self.client.close()
            
    2). # 爬虫文件正常爬取思路
    import scrapy
    from ..items import XiaoxiaoItem
    class MyxiaoSpider(scrapy.Spider):
        name = 'myxiao'
        # allowed_domains = ['www.baidu.com']
        start_urls = ['http://duanziwang.com/']
    
        def parse(self, response):
            div_list = response.xpath('//article[@class="post"]')
            for div in div_list:
                title = div.xpath('./div/h1/a/text()').extract_first()
                cont = div.xpath('./div[2]/p/text()').extract()
                content = ''.join(cont)
                item = XiaoxiaoItem()
                item['title'] = title
                item['content'] = content
                yield item
                
    3). # settings.py 配置
    
    USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'
    
    ROBOTSTXT_OBEY = False
    
    ITEM_PIPELINES = {
        # 跟中间件的类相对应,后面的值,谁小谁先运行
       'xiaoxiao.pipelines.XiaoxiaoPipeline': 300,
    }
    
    MONGO_URI = 'localhost'
    MONGO_DB = 'xiaoxiao'
    
    

    15. scrapy 持久化与Mysql交互

    1). # 在中间管道.py里
    import pymysql
    class MyXiaoxiaoPipeline(object):
        def __init__(self,host,database,user,password,port):
            self.host = host
            self.database = database
            self.user = user
            self.password = password
            self.port = port
    
        def open_spider(self,spider):
            self.client = pymysql.connect(self.host,self.user,self.password,self.database,charset='utf8',port=self.port)
            self.corsor = self.client.cursor()
    	
    
        @classmethod
        def from_crawler(cls,crawler):
            return cls(
                host=crawler.settings.get('MYSQL_HOST'),
                database = crawler.settings.get('MYSQL_DATABASE'),
                user = crawler.settings.get('MYSQL_USER'),
                password = crawler.settings.get('MYSQL_PASSWORD'),
                port = crawler.settings.get('MYSQL_PORT')
            )
    
    
        def process_item(self, item, spider):
            
            
            data = dict(item)
            # data.keys()---->获取所有的键,字段----(title,content)
            keys = ','.join(data.keys())
            # 获取所有的值
            values = ','.join(['%s']*len(data))
            sql = 'insert into %s (%s) values (%s)'% ('myxiao',keys,values)
            self.corsor.execute(sql,tuple(data.values()))
            # 提交
            self.client.commit()
            return item
        
    2).在settings.py 里
    ITEM_PIPELINES = {
       'xiaoxiao.pipelines.MyXiaoxiaoPipeline': 295,
    }
    
    MYSQL_HOST = 'localhost'
    MYSQL_DATABASE = 'xiaoxiao'
    MYSQL_USER = 'root'
    MYSQL_PASSWORD = ''
    MYSQL_PORT = 3306
    
    ROBOTSTXT_OBEY = False
    
    USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'
    
    

    16. 基于crawlSpider的全站数据爬取

    1).# 项目的创建 
    scrapy startproject projectname 
    scrapy genspider -t crawl spidername www.baidu.com
    
    2).# crawlspider全站数据爬取: 
    - CrawlSpider是一个爬虫类, 是scrapy.spider的子类, 功能比spider更强大. 
    - CrawlSpider的机制: 
        - 连接提取器: 可以根据指定的规则进行连接的提取 
        - 规则解析器: 根据指定的规则对响应数据进行解析
            
    3))# 案例: 基于CrawlSpider对笑话网进行全站深度数据爬取, 抓取笑话标题与内容, 并存储于MongoDB中
    # item编码: 
    import scrapy 
    class JokeItem(scrapy.Item): 
        title = scrapy.Field() 
        content = scrapy.Field()
        
    # spider编码: 
    import scrapy 
    from scrapy.linkextractors import LinkExtractor 
    from scrapy.spiders import CrawlSpider, Rule 
    from..items import JokeItem 
    class ZSpider(CrawlSpider): 
        name = 'z' 
        # allowed_domains = ['www.baidu.com'] 
        start_urls = ['http://xiaohua.zol.com.cn/lengxiaohua/'] 
        link = LinkExtractor(allow=r'/lengxiaohua/d+.html') 
        link_detail = LinkExtractor(allow=r'.*?d+.html') 
        rules = ( Rule(link, callback='parse_item', follow=True), 		                   Rule(link_detail, callback='parse_detail'), )
        def parse_item(self, response): 
            pass 
        def parse_detail(self, response): 
            title = response.xpath('//h1[@class="article- title"]/text()').extract_first() 
            content = response.xpath('//div[@class="article- text"]//text()').extract() 
            content = ''.join(content) 
            if title and content: 
                item = JokeItem() 
                item["title"] = title 
                item["content"] = content 
                print(dict(item)) 
                yield item
                
    # pipeline编码: 
    class JokePipeline(object): 
        def __init__(self, mongo_uri, mongo_db): 
            self.mongo_uri = mongo_uri 
            self.mongo_db = mongo_db 
        @classmethod 
        def from_crawler(cls, crawler): 
            return cls( 
                mongo_uri=crawler.settings.get('MONGO_URI'), 			                 				mongo_db=crawler.settings.get('MONGO_DB') ) 
        def open_spider(self, spider):
            self.client = pymongo.MongoClient(self.mongo_uri) 
            self.db = self.client[self.mongo_db] 
        def process_item(self, item, spider):                          				 	             self.db["joke"].insert(dict(item)) 
            return item 
        def close(self, spider): 
            self.client.close()
    

    17. 增量式爬虫

    # 概念: 
    - 检测网站数据更新, 只爬取更新的内容 
    - 核心: 
        去重 
        - url 
        - 数据指纹
    # 增量式爬虫: 电影名称与电影类型的爬取 # url: https://www.4567tv.co/list/index1.html
    
    #item.py
    import scrapy
    class MoveItem(scrapy.Item):
        title = scrapy.Field()
        lab = scrapy.Field()
    #爬虫py文件
    import scrapy
    from ..items import MoveItem
    
    from redis import Redis
    class MymoveSpider(scrapy.Spider):
        name = 'mymove'
        # allowed_domains = ['www.baidu.com']
        start_urls = ['https://www.4567tv.co/list/index1.html']
        # 连接redis数据库
        conn = Redis('localhost',6379)
        def detail_parse(self, response):
            title = response.xpath('//div[@class="ct-c"]/dl/dt/text()').extract_first()
            lab = response.xpath('//div[@class="ee"]/text()').extract_first()
            item = MoveItem()
            item['title'] = title
            item['lab'] = lab
            yield item
        def parse(self, response):
            link = response.xpath('//div[contains(@class,"index-area")]/ul/li/a/@href').extract()
            for i in link:
                # 如果link已经存在, 则ret为0, 说明该数据爬过来
                # 如果link不存在, 则ret为1, 说明没爬虫
                ret = self.conn.sadd('link',i)   # 把需要的数据存入redis库
                #  反向思绪
                if ret:
                    print('有新数据, 可以爬取---------------------------------')
                    yield scrapy.Request(url='https://www.4567tv.co'+i,callback=self.detail_parse)
                else:
                    print('没有数据更新, 不需要爬取###############################')
                    
    # pipelines.py
    import pymongo
    
    class MovePipeline(object):
        def process_item(self, item, spider):
    
            conn = pymongo.MongoClient('localhost',27017)
            db = conn.move
            table = db.mv
            table.insert_one(dict(item))
            return item
        
    # settings.py
    USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'
    ROBOTSTXT_OBEY = False
    ITEM_PIPELINES = {
       'move.pipelines.MovePipeline': 300,
    }
    

    18. redis安装

    1.将安装包解压到一个文件夹下: 如 D:
    edis, 会在该文件夹下看到所有redis的文件 
    2.将该文件夹添加至系统环境变量中 
    3.在解压的文件目录的地址栏上输入cmd, 在cmd窗口中输入redis-server ./redis.windows.conf , 然后回车, 如果出现下面图片的样子说明redis安装成功了
    
    *****************************************************************************************
    启动redis服务端
    	cmd:redis-server ./redis.windows.conf
    启动redis客户端
    	cmd:redis-cli
        # 查询所有键   
        keys *
        #  删除键
        del 键名
        # 添加数据
        sadd name ()
        # 查询所有数据
        lrange xw:item 0 -1
        # 存储
        set name laowang
    OK	# 取出来
    127.0.0.1:6379> get name
    "laowang"
    127.0.0.1:6379>
    
    

    19. mongo的分组聚合统计用django显示

    # 连接Mongo 数据库
    import pymongo
    conn = pymongo.MongoClient('localhost',27017)
    db = conn.fqxh
    table = db.xh
    
    def login(request):
        # find()查询所有的数据
        res = table.find()
        return render(request,'aaa.html',locals())
    
    def index(request):
        # 对都需要的值进行排序ASC是正序,DESC倒叙
        res = table.find().sort([('times_date',pymongo.ASCENDING)])
        return render(request,'index.html',locals())
    
    
    def indexs(request):
        ret = table.aggregate([{'$group':{'_id':'$times_date','cc':{'$sum':'$count'}}}])
        li  = []
        for i in ret:
            i['date'] = i['_id']
            li.append(i)
        return render(request,'indexs.html',locals())
    
    def total(request):
        # Mongo的分组聚合统计,按照日期分
        res = table.aggregate([{'$group':{'_id':'$times_date','cc':{'$sum':1}}}])
        li = []
        for i in res:
            i['date'] = i['_id']
            li.append(i)
        return render(request,'ccc.html',locals())
    
  • 相关阅读:
    严援朝座右铭
    王治郅 请让爱国走下神坛
    Java 事件处理实例
    SAP ERP 与 Oracle ERP 比较
    Gantt Component for Delphi Pure Pascal code(TsyGantt VCL)
    XMLRPC vs. SOAP
    Interfaces with Constants Only(java中通用常量定义)
    船舶设计软件简介
    DelphiARX 2000i 简介
    JAVA事件适配器用内部类,匿名类实现事件处理
  • 原文地址:https://www.cnblogs.com/xinzaiyuan/p/12382294.html
Copyright © 2011-2022 走看看