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

    1. 基本使用

    1.1 定义及安装

    • 为了爬取网站数据,提取结构性数据而编写的应用框架
    • scrapy组件工作流程
    引擎首先会将爬虫文件中的起始url获取,并且提交到调度器中。如果需要从url中下载数据,则调度器会将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 pywin32
        e. pip3 install scrapy
    

    1.2 项目创建

    1、创建项目:scrapy startproject 项目名称
    
    2、目录文件功能
    scrapy.cfg   项目的主配置信息。(真正爬虫相关的配置信息在settings.py文件中)
    items.py     设置数据存储模板,用于结构化数据,如:Django的Model
    pipelines    数据持久化处理
    settings.py  配置文件,如:递归的层数、并发数,延迟下载等
    middlewares  中间件设置
    spiders      爬虫目录,如:创建文件,编写爬虫解析规则
    
    3、创建爬虫应用程序
    (1)cd project_name(进入项目目录)
    (2)scrapy genspider 应用名称 爬取网页的起始url (例如:scrapy genspider qiubai www.qiushibaike.com)
    自动生成py文件:
    import scrapy
    class FirsttestSpider(scrapy.Spider):#爬虫类是基于Spider这个父类
        name = 'firstTest' #爬虫文件的名称
        #允许的域名:
        #allowed_domains = ['www.qiushibaike.com']
        #起始url列表:当前的爬虫文件可以从该列表中存储的url中爬取数据
        start_urls = ['https://www.qiushibaike.com/text/']
    
        #继承与父类的方法:用于解析请求到的页面数据
        def parse(self, response):
            print('haha this is  hehe')
            print(response)
            #xpath函数的返回值是Selector对象(使用xpath表达式解析出来的内容是被存储在了Selecotr对象中)
            #title = response.xpath('//*[@id="qiushi_tag_121076506"]/div[1]/a[2]/h2/text()')[0].extract()
            #extract系列函数的作用是将Selector中的文本数据取出。
            #Selector对象可以直接调用xpath函数。
            title = response.xpath('//*[@id="qiushi_tag_121056271"]/div[1]/a[2]/h2/text()').extract_first()
            title = response.xpath('//*[@id="qiushi_tag_121056271"]/div[1]/a[2]/h2/text()')[0]
            print(title)
    
    (3)scrapy crawl  应用名称  #执行程序
    
    4、基本配置
    settings文件:
    (1)伪装请求载体身份
    USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'
    (2)忽略robots协议
    ROBOTSTXT_OBEY = False
    (3)开启管道(后面数字指定优先级)
    ITEM_PIPELINES = {
       'firstBlood.pipelines.FirstbloodPipeline': 300,
    }
    (4)使用代理ip时中间件设置
    SPIDER_MIDDLEWARES = {
       'firstBlood.middlewares.FirstbloodSpiderMiddleware': 543,
    }
    # 把默认的该成自己定义的类名 :FirstbloodSpiderMiddleware 改成 MyDaili
    ----------------------------------
    注:在middlewares文件写入:
    class MyDaili(object):
        def process_request(self,request,spider):
            #在该方法中设置代理ip
            request.meta['proxy']='http://120.76.231.27:3128'
    
    

    1.3 爬取糗百作者和标题(get请求)

    spiders文件夹(qiutu.py):
    import scrapy
    from qiubai_all.items import QiubaiAllItem
    class QiutuSpider(scrapy.Spider):
        name = 'qiutu'
        #allowed_domains = ['www.qiushibaike.com/pic/']
        start_urls = ['http://www.qiushibaike.com/pic/']
    
        #指定一个页码通用的url
        url = 'https://www.qiushibaike.com/pic/page/%d/?s=5127014'
        pageNum = 1 #控制页码
    
        def parse(self, response):
            div_list = response.xpath('//*[@id="content-left"]/div')
            for div in div_list:
                item = QiubaiAllItem() #创建item对象
                #使用管道进行持久化存储的流程:
                    #1.使用爬虫文件获得解析到的数据
                    #2.将解析到的数据封装存储到items对象中
                    #3.将封装好的items对象提交给管道文件
                    #4.在管道文件中编写持久化存储的代码
                    #5.在settings中开启管道
                item['author']=div.xpath('.//h2/text()').extract_first()
                item['content']=div.xpath('.//div[@class="content"]/span/text()').extract_first()
    
                yield item
    
            #想要对应不同页码的url发起请求
            if self.pageNum <= 35:
                self.pageNum += 1 #从第二页发起请求
    
                print('开始爬取第%d页的数据'%self.pageNum)
                new_url = format(self.url%self.pageNum) #是新页码的url
                #发起请求
                #url:请求的url
                #callback:回调函数(指定解析数据的规则)
                yield scrapy.Request(url=new_url,callback=self.parse)
                
    items文件:
    import scrapy
    class QiubaiAllItem(scrapy.Item):
        # define the fields for your item here like:
        # name = scrapy.Field()
        author = scrapy.Field()
        content = scrapy.Field()
        
    pipelines文件:
    class QiubaiAllPipeline(object):
        def __init__(self):
            self.fp = None
        def open_spider(self,spider):
            print('开始爬虫')
            self.fp = open('./data.txt','w',encoding='utf-8')
    
        def process_item(self, item, spider):
            #1.获取item中的数据
            self.fp.write(item['author']+':'+item['content']+'
    
    ')
            return item
        def close_spider(self,spider):
            print('爬虫结束')
            self.fp.close()
    

    1.4 校花网图片链接及图片名爬取

    spiders文件:
    import scrapy
    from xiaohuaPro.items import XiaohuaproItem
    class XiaohuaSpider(scrapy.Spider):
        name = 'xiaohua'
        #allowed_domains = ['www.521609.com/daxuemeinv']
        start_urls = ['http://www.521609.com/daxuemeinv/']
        url = 'http://www.521609.com/daxuemeinv/list8%d.html'
        page_num = 1
        def parse(self, response):
            li_list = response.xpath('//*[@id="content"]/div[2]/div[2]/ul/li')
            for li in li_list:
                item = XiaohuaproItem()
                item['img_url'] = li.xpath('./a/img/@src').extract_first()
                #拼接图片下载的url
                item['img_url'] = 'http://www.521609.com'+item['img_url']
                item['img_name'] = li.xpath('./a/img/@alt').extract_first()
    
                yield item
            if self.page_num <= 23:
                self.page_num += 1
                url = format(self.url%self.page_num)
                yield scrapy.Request(url=url,callback=self.parse)
    
    items文件:
    import scrapy
    class XiaohuaproItem(scrapy.Item):
        # define the fields for your item here like:
        # name = scrapy.Field()
        img_url = scrapy.Field()
        img_name = scrapy.Field()
        
    pipelines文件:
    import json
    import urllib.request
    import os
    class XiaohuaproPipeline(object):
        def __init__(self):
            self.fp = None
        def open_spider(self,spider):
            print('开始爬虫')
            self.fp = open('./data.json','w',encoding='utf-8')
        def process_item(self, item, spider):
            img_dic = {
                'img_url':item['img_url'],
                'img_name':item['img_name']
            }
            #json.dumps 序列化时对中文默认使用的ascii编码.想输出真正的中文需要指定ensure_ascii=False
            json_string = json.dumps(img_dic,ensure_ascii=False)
            self.fp.write(json_string)
    
            #下载图片操作
            if not os.path.exists('xiaohua'):
                os.mkdir('xiaohua')
            filePath='xiaohua/'+item['img_name']+'.png'
            urllib.request.urlretrieve(url=item['img_url'],filename=filePath)
            print(filePath+ ':下载成功')
    
            return item
        def close_spider(self,spider):
            self.fp.close()
            print('爬虫结束')
    
     #urlretrieve(url, filename=None, reporthook=None, data=None)   有四个参数
     #前两个是下载的地址和保存的路径
     #'参数 reporthook 是一个回调函数,当连接上服务器、以及相应的数据块传输完毕时会触发该回调,我们可以利用这个回调函数来显示当前的下载进度。' 
     # '参数 data 指 post 到服务器的数据,该方法返回一个包含两个元素的(filename, headers)元组,filename 表示保存到本地的路径,header 表示服务器的响应头。'
    
    

    1.5 百度翻译post请求案例

    spiders文件:
    import scrapy
    class PostdemoSpider(scrapy.Spider):
        name = 'postDemo'
        allowed_domains = ['https://fanyi.baidu.com/sug']
        #start_urls = ['http://https://fanyi.baidu.com/sug/']
    
        #该方法就是对start_urls列表中的url发起请求
        #def start_requests(self):  #父类对该方法的默认实现
            #for url in self.start_urls:
                #yield scrapy.Request(url=url,callback=parse)
    
        #重写父类的start_requests方法:该方法默认发起的是get请求
        def start_requests(self):
            post_url = 'https://fanyi.baidu.com/sug/'
            data = {
                'kw':'dog'
            }
            #FormRequest该函数用来发起post请求
            #Request使用用来发起get请求
            yield scrapy.FormRequest(url=post_url,formdata=data,callback=self.parse)
    
        def parse(self, response):
            print(response.text)
            
    pipeline文件:
    class PostproPipeline(object):
        def process_item(self, item, spider):
            return item
    

    1.6 获取二级子页面内容(请求传参)

    import scrapy
    from moviePro.items import MovieproItem
    class MovieSpider(scrapy.Spider):
        name = 'movie'
        #allowed_domains = ['www.id97.com']
        start_urls = ['http://www.id97.com/']
    
        #该方法是用来指定二级子页面的解析规则
        def secondPageParse(self,response):
            #接收Request函数传递过来的参数(meta对应字典的key值),此时得到的item对象即使parse函数中的item= MovieproItem()
            # 再去item文件中加上二级子页面的两个属性(actor,show_time)
            item = response.meta['item']
            item['actor'] = response.xpath('/html/body/div[1]/div/div/div[1]/div[1]/div[2]/table/tbody/tr[1]/td[2]/a/text()').extract_first()
            item['show_time'] = response.xpath('/html/body/div[1]/div/div/div[1]/div[1]/div[2]/table/tbody/tr[7]/td[2]/text()').extract_first()
    
            #将item提交给管道
            yield item
    
        def parse(self, response):
            div_list = response.xpath('/html/body/div[1]/div[2]/div[1]/div/div')
            for div in div_list:
                item = MovieproItem()
                item['name'] = div.xpath('./div/div[@class="meta"]//a/text()').extract_first()
                item['kind'] = div.xpath('./div/div[@class="meta"]/div[@class="otherinfo"]//text()').extract()
                item['kind'] = ''.join(item['kind'])
                item['url'] = div.xpath('./div/div[@class="meta"]//a/@href').extract_first()
                #meta={'item':item} 该参数是用来给回调函数进行传值,指定字典的形式,通过key 传多个值
                yield scrapy.Request(url=item['url'],callback=self.secondPageParse,meta={'item':item})
  • 相关阅读:
    企业微信通讯录替换-JqueryWEUI Picker替换通讯录
    页面window.onload冲突
    企业微信调试工具
    企业微信:错误码:50001 redirect_url 一例问题解决办法
    企业微信通讯录替换-Echarts中使用部门名称
    紫光拼音输入法切换中英文
    企业微信服务商平台申请
    企业微信通讯录替换-根据员工姓名查找工号
    微信开发 40001 invalid credential
    请求验证过程检测到有潜在危险的客户端输入值,对请求的处理已经中止
  • 原文地址:https://www.cnblogs.com/quqinchao/p/9794574.html
Copyright © 2011-2022 走看看