zoukankan      html  css  js  c++  java
  • 爬虫4 scrapy框架1 的安装和启动, scrapy架构, [配置文件, 目录介绍], [以抽屉为例, 爬取数据并解析], 持久化, [动作链, 自动登录12306] , 日志logging, io模型了解

    1 scarpy框架的安装和启动

    # 1 框架 不是 模块
    # 2 号称爬虫界的django(你会发现,跟django很多地方一样)
    # 3 安装
        -mac,linux平台:pip3 install scrapy
      -windows平台:pip3 install scrapy(大部分人可以)
          - 如果失败:
          1、pip3 install wheel #安装后,便支持通过wheel文件安装软件,wheel文件官网:https://www.lfd.uci.edu/~gohlke/pythonlibs
          3、pip3 install lxml
          4、pip3 install pyopenssl
          5、下载并安装pywin32:https://sourceforge.net/projects/pywin32/files/pywin32/
          6、下载twisted的wheel文件:http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
          7、执行pip3 install 下载目录Twisted-17.9.0-cp36-cp36m-win_amd64.whl
          8、pip3 install scrapy
     # 4 在script文件夹下会有scrapy.exe可执行文件
            -创建scrapy项目:scrapy startproject 项目名   (django创建项目)
          -创建爬虫:scrapy genspider 爬虫名 要爬取的网站地址   # 可以创建多个爬虫
        
     # 5 启动爬虫
                -scrapy crawl 爬虫名字
              -scrapy crawl 爬虫名字 --nolog
     # 6 不在命令行下执行爬虫
        -在项目路径下创建一个main.py,右键执行即可
          from scrapy.cmdline import execute
        # execute(['scrapy','crawl','chouti','--nolog'])  # 不打印log,可以在其他地方设置log
        execute(['scrapy','crawl','chouti']) # 对应爬虫类中的名字name = 'chouti'

    2 scrapy架构

    # 1 爬虫起始地址包装成requests发给engine
    # 2 判断如果是请求,发给SCHEDULER进行调度
    # 4 把请求通过下载中间件,发给DOWNLOADER,朝网络发请求(scrapy基于twisted模块io多路复用,同一时刻发送大量请求给网络)[这就是为什么scrapy性能高,因为此处io多路复用模型]
    # 5 响应回来,穿过下载中间件
    # 6 engin吧response通过爬虫中间件返回spiders,就是回调  (这就是为什么spiders类解析parse方法能拿到response)
    # 7 把解析出items或者requests返回engine
    # 8 如果是items发给item pipelines保存处理,如果是requests对象,在发给scheduler调度器准备再次爬取(3,4,5,6)
    
    # 引擎(EGINE)(大总管)
    引擎负责控制系统所有组件之间的数据流,并在某些动作发生时触发事件。有关详细信息,请参见上面的数据流部分。
    # 调度器(SCHEDULER)
    用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL的优先级队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址(必须是爬过有数据返回才行,如果爬取当中异常,超时都算没有爬过)
    # 下载器(DOWLOADER)
    用于下载网页内容, 并将网页内容返回给EGINE,下载器是建立在twisted这个高效的异步模型上的
    # 爬虫(SPIDERS)
    SPIDERS是开发人员自定义的类,用来解析responses,并且提取items,或者发送新的请求
    # 项目管道(ITEM PIPLINES)
    在items被提取后负责处理它们,主要包括清理、验证、持久化(比如存到数据库)等操作
    
    
    # 两个中间件
    -爬虫中间件
    -下载中间件(用的最多,加头,加代理,加cookie,集成selenium)

    3 配置文件,目录介绍

    -crawl_chouti   # 项目名
      -crawl_chouti # 跟项目一个名,文件夹
        -spiders    # spiders:放着爬虫  genspider生成的爬虫,都放在这下面
            -__init__.py
          -chouti.py # 抽屉爬虫
          -cnblogs.py # cnblogs 爬虫
        -items.py     # 对比django中的models.py文件 ,写一个个的模型类
        -middlewares.py  # 中间件(爬虫中间件,下载中间件),中间件写在这
        -pipelines.py   # 写持久化的地方(持久化到文件,mysql,redis,mongodb)
        -settings.py    # 配置文件
      -scrapy.cfg       # 不用关注,上线相关的
      
      
      
      
    # 配置文件  settings.py
    ROBOTSTXT_OBEY = False   # 是否遵循爬虫协议,强行运行
    USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'    # 请求头中的ua
    LOG_LEVEL='ERROR' # 这样配置,程序错误信息才会打印,        增加字段,必须大写
        #启动爬虫直接 scrapy crawl 爬虫名   就没有日志输出
      # scrapy crawl 爬虫名 --nolog
    
    
    
    # 爬虫文件   spiders文件夹下
    class ChoutiSpider(scrapy.Spider):
        name = 'chouti'   # 爬虫名字
        allowed_domains = ['https://dig.chouti.com/']  # 允许爬取的域
        start_urls = ['https://dig.chouti.com/']   # 起始爬取的位置,爬虫一启动,会先向它发请求
    
        def parse(self, response):  # 解析,请求回来,自动执行parser,在这个方法中做解析  response为响应对象
            print('---------------------------',response)

    4 以抽屉为例,爬取数据并解析

    # 1 解析,可以使用bs4解析
    from bs4 import BeautifulSoup
    soup=BeautifulSoup(response.text,'lxml')
    soup.find_all()
    # 2 内置的解析器
    # response.css  
    # response.xpath
    
    # 解析 
      # 所有用css或者xpath选择出来的都放在列表中
      # 取第一个:extract_first()
      # 取出所有extract()
      # css选择器取文本和属性:
        # .link-title::text
        # .link-title::attr(href)
      # xpath选择器取文本和属性
        # .//a[contains(@class,"link-title")/text()]
        #.//a[contains(@class,"link-title")/@href]

    css选择器代码示例:

    # crawl_chouti/crawl_chouti/spiders/chouti.py
    import scrapy
    
    class ChoutiSpider(scrapy.Spider):
        name = 'chouti'
        allowed_domains = ['https://dig.chouti.com/']
        start_urls = ['https://dig.chouti.com//']
    
        def parse(self, response):
            # print('------------',response)
            # print(type(response))
            # from scrapy.http.response.html import HtmlResponse
    
            ## 解析 用css解析
            # 所有用css或者xpath选择出来的都放在列表中
            # 取第一个:extract_first()
            # 取所有:extract()
            # 需要取列表的第一个值
            div_list = response.css('div.link-item')
            for div in div_list:
                title = div.css('.link-title::text').extract_first()    # .link-title::text取出文本
                url = div.css('.link-title::attr(href)').extract_first()    # .link-title::attr(href)取出href属性
                img_url = div.css('.matching::attr(src)').extract_first()
                # print(title)
                # print(url)
                # print(img_url)
                print('''
                新闻标题:%s
                新闻连接:%s
                新闻图片:%s
                '''%(title,url,img_url))

    xpath选择器代码示例:

    # crawl_chouti/crawl_chouti/spiders/chouti.py
    import scrapy
    
    class ChoutiSpider(scrapy.Spider):
        name = 'chouti'
        allowed_domains = ['https://dig.chouti.com/']
        start_urls = ['https://dig.chouti.com//']
    
        def parse(self, response):
            # xpath选择器提取数据
            div_list = response.xpath('//div[contains(@class,"link-area")]')
            for div in div_list:
                title = div.xpath('.//a[contains(@class,"link-title")]/text()').extract_first()    
                url = div.xpath('.//a[contains(@class,"link-title")]/@href').extract_first()    
                img_url = div.xpath('//*[contains(@class,"matching")]/@src').extract_first()
                print('''
                新闻标题:%s
                新闻连接:%s
                新闻图片:%s
                '''%(title,url,img_url))

    5 持久化

    # 方式一(讲完就忘了)
        -1 parser解析函数,return 列表,列表套字典
      -2 scrapy crawl chouti -o aa.json   (支持:('json', 'jsonlines', 'jl', 'csv', 'xml', 'marshal', 'pickle')  # 得到的aa.json文件可以通过 https://www.json.cn/ 解析
    # 方式二 pipline的方式(管道)
       -1 在items.py中创建模型类
       -2 在爬虫中chouti.py,引入,把解析的数据放到item对象中(要用中括号)
       -3 yield item对象
       -4 配置文件配置管道
           ITEM_PIPELINES = {
            # 数字表示优先级(数字越小,优先级越大)
           'crawl_chouti.pipelines.CrawlChoutiPipeline': 300,
           'crawl_chouti.pipelines.CrawlChoutiRedisPipeline': 301,
            }
      -5 pipline.py中写持久化的类
              -spider_open       # 执行pipeline类一开始执行 (用open_spider和close_spider会加锁,保证数据不丢失)
              -spider_close      # 执行pipeline结束时执行
              -process_item(在这写保存到哪)

    在文件中保存代码示例

    # crawl_chouti/crawl_chouti/items
    import scrapy
    
    # 写一个模型类,用来存储解析出来的数据
    class CrawlChoutiItem(scrapy.Item):
        title = scrapy.Field()
        url = scrapy.Field()
        img_url = scrapy.Field()
        
    # crawl_chouti/crawl_chouti/spiders/chouti.py
    import scrapy
    
    from crawl_chouti.items import CrawlChoutiItem
    class ChoutiSpider(scrapy.Spider):
        name = 'chouti'
        allowed_domains = ['https://dig.chouti.com/']
        start_urls = ['https://dig.chouti.com//']
        def parse(self, response):
    
            div_list = response.xpath('//div[contains(@class,"link-area")]')
            for div in div_list:
                title = div.xpath('.//a[contains(@class,"link-title")]/text()').extract_first()    # .link-title::text取出文本
                url = div.xpath('.//a[contains(@class,"link-title")]/@href').extract_first()    # .link-title::attr(href)取出href属性
                img_url = div.xpath('//*[contains(@class,"matching")]/@src').extract_first()
                # print('''
                # 新闻标题:%s
                # 新闻连接:%s
                # 新闻图片:%s
                # '''%(title,url,img_url))
                item = CrawlChoutiItem()
                # 这种方式不行,必须使用中括号方式
                # item.title = title   报错
                item['title'] = title
                item['url'] = url
                item['img_url'] = img_url
    
               # 注意用yield,用return只执行一次
                # return item
                yield item    
                
    # crawl_chouti/crawl_chouti/settings.py
    ITEM_PIPELINES = {
        # 数字表示优先级(数字越小,优先级越大)
       'crawl_chouti.pipelines.CrawlChoutiPipeline': 300,
       # 'crawl_chouti.pipelines.CrawlChoutMysqliPipeline': 301,
    }
    
    # crawl_chouti/crawl_chouti/pipelines.py
    class CrawlChoutiPipeline(object):
        def open_spider(self,spider):   # 一开始执行 (用open_spider和close_spider会加锁,保证数据不丢失)
            print('我开始')
            # 打开文件
            self.f = open('a.txt','w')
        # 存文件
        def process_item(self, item, spider):#item为chouti返回的25个item对象。其中spider参数为spiders文件夹下爬虫的类,spider.name获取名字
            print(item)
            # with open('a.txt','w') as f:  # 此处换a写入,如果不用open/close_spider方法,会存在写入数据丢失情况,因为在不同线程中
            #     f.write(item['title'])
            #     f.write(item['url'])
            #     f.write(item['img_url'])
            #     f.write('
    ')
            self.f.write(item['title'])
            self.f.write(item['url'])
            self.f.write(item['img_url'])
            self.f.write('
    ')
            return item    # 继续往下走,如果没有,后续的pipeline类就无法拿到
    
        def close_spider(self,spider):  # 结束时执行
            print('我结束')
            self.f.close()

    在文件和redis数据库中保存代码示例

    # crawl_chouti/crawl_chouti/items
    import scrapy
    
    # 写一个模型类,用来存储解析出来的数据
    class CrawlChoutiItem(scrapy.Item):
        id = scrapy.Field()
        title = scrapy.Field()
        url = scrapy.Field()
        img_url = scrapy.Field()
    
    # crawl_chouti/crawl_chouti/spiders/chouti.py
    import scrapy
    
    from crawl_chouti.items import CrawlChoutiItem
    class ChoutiSpider(scrapy.Spider):
        name = 'chouti'
        allowed_domains = ['https://dig.chouti.com/']
        start_urls = ['https://dig.chouti.com//']
        def parse(self, response):
    
            div_list = response.xpath('//div[contains(@class,"link-area")]')
            for div in div_list:
                title = div.xpath('.//a[contains(@class,"link-title")]/text()').extract_first()    # .link-title::text取出文本
                url = div.xpath('.//a[contains(@class,"link-title")]/@href').extract_first()    # .link-title::attr(href)取出href属性
                img_url = div.xpath('//*[contains(@class,"matching")]/@src').extract_first()
                id = div.xpath('.//a[contains(@class,"link-title")]/@data-id').extract_first()
                # print('''
                # 新闻标题:%s
                # 新闻连接:%s
                # 新闻图片:%s
                # '''%(title,url,img_url))
                item = CrawlChoutiItem()
                # 这种方式不行,必须使用中括号方式
                # item.title = title   报错
                item['title'] = title
                item['url'] = url
                item['img_url'] = img_url
                item['id'] = id
                # 注意用yield,用return只执行一次
                # return item
                yield item
    
    # crawl_chouti/crawl_chouti/settings.py
    ITEM_PIPELINES = {
       # 数字表示优先级(数字越小,优先级越大)
       'crawl_chouti.pipelines.CrawlChoutiPipeline': 300,
       'crawl_chouti.pipelines.CrawlChoutRedisPipeline': 301,
    }
    
    # crawl_chouti/crawl_chouti/pipelines.py
    from redis import Redis
    
    class CrawlChoutiPipeline(object):
        def open_spider(self,spider):   # 一开始 (用open_spider和close_spider会加锁,保证数据不丢失)
            print('我开始')
            # 打开文件
            self.f = open('a.txt','w')
        # 存文件
        def process_item(self, item, spider):   # item为chouti返回的25个item对象
            print(item)
            # with open('a.txt','w') as f:  # 此处换a写入,如果不用open/close_spider方法,会存在写入数据丢失情况,因为在不同线程中
            #     f.write(item['title'])
            #     f.write(item['url'])
            #     f.write(item['img_url'])
            #     f.write('
    ')
            self.f.write(item['title'])
            self.f.write(item['url'])
            self.f.write(item['img_url'])
            self.f.write('
    ')
            return item     # 继续往下走,如果没有,后续的pipeline类就无法拿到
    
        def close_spider(self,spider):  # 结束
            print('我结束')
            self.f.close()
    
    class CrawlChoutRedisPipeline(object):
        # 存redis数据库
    
        def open_spider(self,spider):   # 一开始执行 (用open_spider和close_spider会加锁,保证数据不丢失)
            self.conn = Redis(password='admin123')
    
        def close_spider(self,spider):  # 结束时执行
            pass
    
        def process_item(self, item, spider):
            import json
            s = json.dumps({'title': item['title'], 'url': item['url'], 'img_url': item['img_url']})
            self.conn.hset('chouti_article',item['id'],s) 存入redis,'chouti_article'为redis的类
            return item

    6 动作链,自动登录12306

    # 1 生成一个动作练对象
    action=ActionChains(bro)
    # 2 点击并夯住某个控件
    action.click_and_hold(div)
    # 3 移动(三种方式)
    # action.move_by_offset() # 通过坐标
    # action.move_to_element() # 到另一个标签
    # action.move_to_element_with_offset() # 到另一个标签,再偏移一部分
    
    # 4 真正的移动
    action.perform()
    
    # 5 释放控件(松开鼠标)
    action.release()

    动作链示例代码:

    from selenium import webdriver
    from selenium.webdriver import ActionChains
    import time
    bro=webdriver.Chrome(executable_path='./chromedriver')
    bro.get('https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
    
    bro.implicitly_wait(10)
    
    #切换frame(很少)
    bro.switch_to.frame('iframeResult') #iframe是在标签内还能创建一个html标签,此处切换到内部的html中
    
    div=bro.find_element_by_xpath('//*[@id="draggable"]')
    
    # 使用动作链
    #得到一个动作练对象
    action=ActionChains(bro)
    
    # 使用动作链
    #点击并且夯住
    action.click_and_hold(div)
    
    # 直接把上面的div移动到某个元素上
    # action.move_to_element(元素控件)
    # 移动x坐标,y坐标
    
    # 三种移动方式
    # action.move_by_offset() # 通过坐标
    # action.move_to_element() # 到另一个标签
    # action.move_to_element_with_offset() # 到另一个标签,再偏移一部分
    
    for i in range(5):
        action.move_by_offset(10,10)
    
    # 直接把上面的div移动到某个元素上的某个位置
    # action.move_to_element_with_offset()
    
    # 调用它,会动起来
    action.perform()
    
    time.sleep(1)
    
    #释放动作链
    action.release()
    time.sleep(5)
    bro.close()

    自动登录12306(先用selenium通过超级鹰识别登录获得cookies,然后通过cookies用requests登录)

    # 12306.py
    # 自动登录12306
    
    # pip3 install pillow
    
    from PIL import Image
    from chaojiying import Chaojiying_Client
    from selenium import webdriver
    from selenium.webdriver import ActionChains
    import time
    import json
    import requests
    bro =webdriver.Chrome(executable_path='./chromedriver')
    bro.get('https://kyfw.12306.cn/otn/login/init')
    
    bro.implicitly_wait(10)
    
    # 因为selenium没有直接截取某个元素的功能,现在需要截取全图,然后通过图形软件,再把小图扣出来
    # bro.minimize_window()  #最小化
    # bro.maximize_window() #最大化
    # save_screenshot 截取整个屏幕
    bro.save_screenshot('main.png')
    tag_code =bro.find_element_by_xpath('//*[@id="loginForm"]/div/ul[2]/li[4]/div/div/div[3]/img')
    
    # 查看控件的位置和大小
    size =tag_code.size
    location =tag_code.location
    print(size)
    print(location)
    
    img_tu = (int(location['x']) ,int(location['y']) ,int(location['x' ] +size['width']) ,int(location['y' ] +size['height']))
    # # 抠出验证码
    # #打开
    img =Image.open('./main.png')
    # 抠图
    fram =img.crop(img_tu)
    # 截出来的小图
    fram.save('code.png')
    
    # 调用超级鹰,破解
    
    def get_result():
        chaojiying = Chaojiying_Client('306334xxx', 'lqzxxx', '903641')  # 用户中心>>软件ID 生成一个替换 96001
        im = open('code.png', 'rb').read()  # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
        print(chaojiying.PostPic(im, 9004)) # 1902 验证码类型  官方网站>>价格体系 3.4+版 print 后要加()
        return chaojiying.PostPic(im, 9004)['pic_str']
    
    
    # 返回结果如果有多个 260,133|123,233,处理这种格式[[260,133],[123,233]]
    result=get_result()
    all_list=[]
    if '|' in result:
        list_1 = result.split('|')
        count_1 = len(list_1)
        for i in range(count_1):
            xy_list = []
            x = int(list_1[i].split(',')[0])
            y = int(list_1[i].split(',')[1])
            xy_list.append(x)
            xy_list.append(y)
            all_list.append(xy_list)
    else:
        x = int(result.split(',')[0])
        y = int(result.split(',')[1])
        xy_list = []
        xy_list.append(x)
        xy_list.append(y)
        all_list.append(xy_list)
    print(all_list)
    
    # 用动作链,点击图片
    # [[260,133],[123,233]]
    for a in all_list:
        x = a[0]
        y = a[1]
        ActionChains(bro).move_to_element_with_offset(tag_code, x, y).click().perform()
        time.sleep(1)
    username=bro.find_element_by_id('username')
    username.send_keys("")  # 用户名
    pwd=bro.find_element_by_id('password')
    pwd.send_keys('')   # 密码
    submit=bro.find_element_by_id('loginSub')
    submit.click()
    
    #获取cookie
    # 使用requests模块,携带cookie朝某个接口发请求
    time.sleep(3)
    c = bro.get_cookies()
    print(c)
    with open('xxx.json', 'w') as f:
        json.dump(c, f)
    
    
    # cookies = {}
    # # 获取cookie中的name和value,转化成requests可以使用的形式
    # for cookie in c:
    #     cookies[cookie['name']] = cookie['value']
    #
    # print(cookies)
    #
    with open('xxx.json', 'r') as f:
        di = json.load(f)
    cookies = {}
    # 获取cookie中的name和value,转化成requests可以使用的形式
    for cookie in di:
        cookies[cookie['name']] = cookie['value']
    
    print('---------')
    print(cookies)
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36',
        'Referer': 'https://kyfw.12306.cn/otn/view/information.html',
        'Origin': 'https://kyfw.12306.cn',
        'Host': 'kyfw.12306.cn',
        'Sec-Fetch-Dest': 'empty',
        'Sec-Fetch-Mode': 'cors',
        'Sec-Fetch-Site': 'same-origin',
        'X-Requested-With': 'XMLHttpRequest',
        # 'Cookie':'JSESSIONID=5E0ADB0562F67D12821C1031B4C0D6C5; tk=h8F7smXhBU8PH3aIYHxCu5fR86HnywJ7BNF8sAets1s0; route=9036359bb8a8a461c164a04f8f50b252; BIGipServerpool_passport=233636362.50215.0000; RAIL_EXPIRATION=1586657272770; RAIL_DEVICEID=mWh29ziIiHHcSeSRm2Lp4kpamkdA3c6Cpi9gDQQN_rTcgI5UPn_FyMY8mdO5Vinhk4vyn_zW-rP2bmqeO8WKSzsuhOMhGru6qIQCIVDIYPEJtIF7PfoQkSD8koFHdQ9pLaUH5jwoYeYqxM6bA0GRghJELkd2zvHs; BIGipServerpassport=971505930.50215.0000; BIGipServerotn=1105723658.24610.0000'
        # 'Cookie':json.dumps(cookies)
    }
    #https://kyfw.12306.cn/otn/modifyUser/initQueryUserInfoApi
    res = requests.post('https://kyfw.12306.cn/otn/modifyUser/initQueryUserInfoApi',headers=headers,
                      cookies=cookies )
    print(res.cookies.get_dict())
    print(res.text)

    超级鹰代码(就是网上的测试代码改了bug,同上篇爬虫博客)

    # chaojiying.py
    import requests
    from hashlib import md5
    
    
    class Chaojiying_Client(object):
    
        def __init__(self, username, password, soft_id):
            self.username = username
            password = password.encode('utf8')
    
            self.password = md5(password).hexdigest()
            self.soft_id = soft_id
            self.base_params = {
                'user': self.username,
                'pass2': self.password,
                'softid': self.soft_id,
            }
            self.headers = {
                'Connection': 'Keep-Alive',
                'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
            }
    
    
        def PostPic(self, im, codetype):
            """
            im: 图片字节
            codetype: 题目类型 参考 http://www.chaojiying.com/price.html
            """
            params = {
                'codetype': codetype,
            }
            params.update(self.base_params)
            files = {'userfile': ('ccc.jpg', im)}
            r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files,
                              headers=self.headers)
            return r.json()
    
    
        def ReportError(self, im_id):
            """
            im_id:报错题目的图片ID
            """
            params = {
                'id': im_id,
            }
            params.update(self.base_params)
            r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
            return r.json()
    
    
    if __name__ == '__main__':
        chaojiying = Chaojiying_Client('306334xxx', 'lqzxxx', '903641')  # 用户中心>>软件ID 生成一个替换 96001
        im = open('a.jpg', 'rb').read()  # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
        print(chaojiying.PostPic(im, 1902)) # 1902 验证码类型  官方网站>>价格体系 3.4+版 print 后要加()
    View Code

    总结:

    # 有没有面试机会,取决于你的简历(简历,是可以润色的)3年工作经验,激进一些,不要那么保守
        # 属性python,熟悉oop,熟悉pep8规范
      # 熟悉django,flask
      # 了解redis,了解linux,能部署项目
      # 了解celery,能简单的集成到django中
    # 能不能入职,取决于你的面试表现
    
    # 1 scrapy 安装:pip3 install scray
    # 2 scrapy startproject 项目名字
    # 3 scrapy genspider 爬虫名字 地址
    # 4 目录结构
    # 5 架构:5大组件,2大中间件
    # 6 以抽屉为例:css选择器和xpath选择器
            -extract()
          -extract_first()
        -css文本:     ::text
        -css属性:    ::attr(属性名)
        -xpath文本:    /text()
        -xpath属性:    /@属性名
    # 7 持久化的两种方案
        -用命令 scrapy crawl 爬虫 -o 文件名.json   (parser:必须return 列表)
      -通过管道方式
          -1 写一个模型类
        -2 爬虫的parser函数中,把解析出的数据,放到模型类对象中 yield 对象
        -3 在setting中配置(数字越小,优先级越高)
        -4 piplins中写一个类, open_spider  close_spider process_item(是否:return)
        
     # 8 动作链(了解)    自动登录12306(登录不是你的目的)cookie:能自动登录就登陆,不能就手动登陆
             -获取到cookie:redis(搭建cookie池)
          -只是定时任务(apscheduler)
        -celery:定时任务和异步任务
        -windows 不支持(明明白白写的,不支持windows)

    日志logging

    1、 意义 :
    为了方便在调试。在scrapy运行中可能停不下来, 关闭就没有记录了。因此把日志保存在文本中方便看信息。

    2 、使用:
    1) 在settings中增加:

    # settings
    # 日志处理
    import datetime
    import os
    Today = datetime.datetime.now() # 取得现在的时间
    if not os.path.exists('log'):
        os.mkdir('log')
    Log_file_path = 'log/scrapy_{}_{}_{}.log'.format(Today.year,Today.month,Today.day)  # 以时间为文件名
    LOG_LEVEL='WARNING'
    LOG_FILE = Log_file_path

    Scrapy提供5层logging级别:

    CRITICAL - 严重错误

    ERROR - 一般错误

    WARNING - 警告信息

    INFO - 一般信息

    DEBUG - 调试信息

    logging设置
    通过在setting.py中进行以下设置可以被用来配置logging:

    LOG_ENABLED 默认: True,启用logging

    LOG_ENCODING 默认: ‘utf-8’,logging使用的编码

    LOG_FILE 默认: None,在当前目录里创建logging输出文件的文件名

    LOG_LEVEL 默认: ‘DEBUG’,log的最低级别
    2)具体的使用:

    import logging
    logging.warning('日志信息')
    logging.info('这是info信息,逗逗你')

    1 io模型

    http://www.liuqingzheng.top/python/Python异步IO并发/3-IO操作与IO模型/ ,epoll和select,poll

     

  • 相关阅读:
    如何在Windows 7平台搭建Android Cocos2d-x3.2alpha0开发环境
    boost::unordered_map分析和使用(转)
    #、##、__VA_ARGS__和##__VA_ARGS__的作用(转)
    C++ explicit关键字详解(转)
    C++11的auto关键字
    Nagios监控系统
    CentOS6.5安装oracle11
    Centos7系统中Mysql登录忘记root密码
    在Centos7系统上查看Mysql版本的方法
    忘记Redhat7root密码
  • 原文地址:https://www.cnblogs.com/ludingchao/p/12677176.html
Copyright © 2011-2022 走看看