网络爬虫-07

Spider06回顾

scrapy框架

  • 五大组件+工作流程+常用命令

    1】五大组件
        1.1) 引擎(Engine)
        1.2) 爬虫程序(Spider)
        1.3) 调度器(Scheduler)
        1.4) 下载器(Downloader)
        1.5) 管道文件(Pipeline)
        1.6) 下载器中间件(Downloader Middlewares)
        1.7) 蜘蛛中间件(Spider Middlewares)
        
    【2】工作流程
        2.1) Engine向Spider索要URL,交给Scheduler入队列
        2.2) Scheduler处理后出队列,通过Downloader Middlewares交给Downloader去下载
        2.3) Downloader得到响应后,通过Spider Middlewares交给Spider
        2.4) Spider数据提取:
           a) 数据交给Pipeline处理
           b) 需要跟进URL,继续交给Scheduler入队列,依次循环
        
    【3】常用命令
        3.1) scrapy startproject 项目名
        3.2) scrapy genspider 爬虫名 域名
        3.3) scrapy crawl 爬虫名
    

完成scrapy项目完整流程

  • 完整流程

    1】scrapy startproject Tencent
    【2】cd Tencent
    【3】scrapy genspider tencent tencent.com
    【4】items.py(定义爬取数据结构)
        import scrapy
        class TencentItem(scrapy.Item):
            name = scrapy.Field()
            address = scrapy.Field()5】tencent.py(写爬虫文件)
        import scrapy
        from ..items import TencentItem
        class TencentSpider(scrapy.Spider):
            name = 'tencent'
            allowed_domains = ['tencent.com']
            start_urls = ['']
            def parse(self, response):
                item = TencentItem()
                item['name'] = xxxx
                yield item
    
    【6】pipelines.py(数据处理)
        class TencentPipeline(object):
            def process_item(self, item, spider):
                return item
        
    【7】settings.py(全局配置)8】run.py 
        from scrapy import cmdline
        cmdline.execute('scrapy crawl tencent'.split())
    

我们必须记住

  • 熟练记住

    1】响应对象response属性及方法
        1.1) response.text :获取响应内容 - 字符串
        1.2) response.body :获取bytes数据类型
        1.3) response.xpath('')
        1.4) response.xpath('').extract() :提取文本内容,将列表中所有元素序列化为Unicode字符串
        1.5) response.xpath('').extract_first() :序列化提取列表中第1个文本内容
        1.6) response.xpath('').get() : 提取列表中第1个文本内容(等同于extract_first())2】settings.py中常用变量
        2.1) 设置数据导出编码(主要针对于json文件)
             FEED_EXPORT_ENCODING = 'utf-8'
        2.2) 设置User-Agent
             USER_AGENT = ''
        2.3) 设置最大并发数(默认为16)
             CONCURRENT_REQUESTS = 32
        2.4) 下载延迟时间(每隔多长时间请求一个网页)
             DOWNLOAD_DELAY = 0.5
        2.5) 请求头
             DEFAULT_REQUEST_HEADERS = {'Cookie' : 'xxx'}
        2.6) 添加项目管道
             ITEM_PIPELINES = {'目录名.pipelines.类名' : 优先级}
        2.7) cookie(默认禁用,取消注释-True|False都为开启)
             COOKIES_ENABLED = False
    

爬虫项目启动方式

  • 启动方式

    1】方式一:基于start_urls
        1.1) 从爬虫文件(spider)的start_urls变量中遍历URL地址交给调度器入队列,
        1.2) 把下载器返回的响应对象(response)交给爬虫文件的parse(self,response)函数处理
    
    【2】方式二
        重写start_requests()方法,从此方法中获取URL,交给指定的callback解析函数处理
        2.1) 去掉start_urls变量
        2.2) def start_requests(self):
                 # 生成要爬取的URL地址,利用scrapy.Request()方法交给调度器
    

数据持久化存储

  • MySQL-MongoDB-Json-csv

    ***************************存入MySQL、MongoDB****************************1】在setting.py中定义相关变量
    【2】pipelines.py中新建管道类,并导入settings模块
    	def open_spider(self,spider):
    		# 爬虫开始执行1次,用于数据库连接
            
    	def process_item(self,item,spider):
            # 用于处理抓取的item数据
            return item
        
    	def close_spider(self,spider):
    		# 爬虫结束时执行1次,用于断开数据库连接3】settings.py中添加此管道
    	ITEM_PIPELINES = {'':200}
    
    【注意】 process_item() 函数中一定要 return item
    
    ********************************存入JSON、CSV文件***********************
    scrapy crawl maoyan -o maoyan.csv
    scrapy crawl maoyan -o maoyan.json
    【注意】
        存入json文件时候需要添加变量(settings.py) : FEED_EXPORT_ENCODING = 'utf-8'
    

Spider07笔记

分布式爬虫

  • 分布式爬虫介绍

    1】原理
        多台主机共享1个爬取队列
        
    【2】实现
        2.1) 重写scrapy调度器(scrapy_redis模块)
        2.2) sudo pip3 install scrapy_redis
    
  • 为什么使用redis

    1】Redis基于内存,速度快
    【2】Redis非关系型数据库,Redis中集合,存储每个request的指纹
    

scrapy_redis详解

  • GitHub地址

    https://github.com/rmax/scrapy-redis
    
  • settings.py说明

    # 重新指定调度器: 启用Redis调度存储请求队列
    SCHEDULER = "scrapy_redis.scheduler.Scheduler"
    
    # 重新指定去重机制: 确保所有的爬虫通过Redis去重
    DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
    
    # 不清除Redis队列: 暂停/恢复/断点续爬(默认清除为False,设置为True不清除)
    SCHEDULER_PERSIST = True
    
    # 优先级队列 (默认)
    SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue'
    #可选用的其它队列
    # 先进先出
    SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.FifoQueue'
    # 后进先出
    SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.LifoQueue'
    
    # redis管道
    ITEM_PIPELINES = {
        'scrapy_redis.pipelines.RedisPipeline': 300
    }
    
    #指定连接到redis时使用的端口和地址
    REDIS_HOST = 'localhost'
    REDIS_PORT = 6379
    

腾讯招聘分布式改写

  • 分布式爬虫完成步骤

    1】首先完成非分布式scrapy爬虫 : 正常scrapy爬虫项目抓取
    【2】设置,部署成为分布式爬虫
    
  • 分布式环境说明

    1】分布式爬虫服务器数量: 2(其中1台Windows,1台Ubuntu虚拟机)
    【2】服务器分工:
        2.1) Windows : 负责数据抓取
        2.2) Ubuntu  : 负责URL地址统一管理,同时负责数据抓取
    
  • 腾讯招聘分布式爬虫 - 数据同时存入1个Redis数据库

    1】完成正常scrapy项目数据抓取(非分布式 - 拷贝之前的Tencent)
    
    【2】设置settings.py,完成分布式设置
        2.1-必须) 使用scrapy_redis的调度器
             SCHEDULER = "scrapy_redis.scheduler.Scheduler"
            
        2.2-必须) 使用scrapy_redis的去重机制
             DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
            
        2.3-必须) 定义redis主机地址和端口号
             REDIS_HOST = '192.168.1.107'
             REDIS_PORT = 6379
            
        2.4-非必须) 是否清除请求指纹,True:不清除 False:清除(默认)
             SCHEDULER_PERSIST = True
            
        2.5-非必须) 在ITEM_PIPELINES中添加redis管道,数据将会存入redis数据库
             'scrapy_redis.pipelines.RedisPipeline': 2003】把代码原封不动的拷贝到分布式中的其他爬虫服务器,同时开始运行爬虫
    
    【结果】:多台机器同时抓取,数据会统一存到Ubuntu的redis中,而且所抓数据不重复
    
  • 腾讯招聘分布式爬虫 - 数据存入MySQL数据库

    """和数据存入redis步骤基本一样,只是变更一下管道和MySQL数据库服务器的IP地址"""1】settings.py
        1.1) SCHEDULER = 'scrapy_redis.scheduler.Scheduler'
        1.2) DUPEFILTER_CLASS = 'scrapy_redis.dupefilter.RFPDupeFilter'
        1.3) SCHEDULER_PERSIST = True
        1.4) REDIS_HOST = '192.168.1.105'
        1.5) REDIS_PORT = 6379
        1.6) ITEM_PIPELINES = {'Tencent.pipelines.TencentMysqlPipeline' : 300}
        1.7) MYSQL_HOST = '192.168.1.105'2】将代码拷贝到分布式中所有爬虫服务器
    
    【3】多台爬虫服务器同时运行scrapy爬虫
    
    # 赠送腾讯MySQL数据库建库建表语句
    """
    create database tencentdb charset utf8;
    use tencentdb;
    create table tencenttab(
    job_name varchar(1000),
    job_type varchar(200),
    job_duty varchar(5000),
    job_require varchar(5000),
    job_address varchar(200),
    job_time varchar(200)
    )charset=utf8;
    """
    

机器视觉与tesseract

  • 概述

    1】作用
        处理图形验证码
    
    【2】三个重要概念 - OCR、tesseract-ocr、pytesseract
        2.1) OCR
            光学字符识别(Optical Character Recognition),通过扫描等光学输入方式将各种票据、报刊、书籍、文稿及其它印刷品的文字转化为图像信息,再利用文字识别技术将图像信息转化为电子文本
    
        2.2) tesseract-ocr
            OCR的一个底层识别库(不是模块,不能导入),由Google维护的开源OCR识别库
    
        2.3) pytesseract
            Python模块,可调用底层识别库,是对tesseract-ocr做的一层Python API封装
    
  • 安装tesseract-ocr

    1】Ubuntu安装
        sudo apt-get install tesseract-ocr
    
    【2】Windows安装
        2.1) 下载安装包
        2.2) 添加到环境变量(Path)3】测试(终端 | cmd命令行)
        tesseract xxx.jpg 文件名
    
  • 安装pytesseract

    1】安装
        sudo pip3 install pytesseract
        
    【2】使用示例
        import pytesseract
        # Python图片处理库
        from PIL import Image
    
        # 创建图片对象
        img = Image.open('test1.jpg')
        # 图片转字符串
        result = pytesseract.image_to_string(img)
        print(result)
    

补充 - 滑块缺口验证码案例

豆瓣网登录

  • 案例说明

    1】URL地址: https://www.douban.com/2】先输入几次错误的密码,让登录出现滑块缺口验证,以便于我们破解
    【3】模拟人的行为
        3.1) 先快速滑动
        3.2) 到离重点位置不远的地方开始减速
    【4】详细看代码注释
    
  • 代码实现

    """
    说明:先输入几次错误的密码,出现滑块缺口验证码
    """
    from selenium import webdriver
    # 导入鼠标事件类
    from selenium.webdriver import ActionChains
    import time
    
    # 加速度函数
    def get_tracks(distance):
        """
        拿到移动轨迹,模仿人的滑动行为,先匀加速后匀减速
        匀变速运动基本公式:
        ①v=v0+at
        ②s=v0t+½at²
        """
        # 初速度
        v = 0
        # 单位时间为0.3s来统计轨迹,轨迹即0.3内的位移
        t = 0.3
        # 位置/轨迹列表,列表内的一个元素代表0.3s的位移
        tracks = []
        # 当前的位移
        current = 0
        # 到达mid值开始减速
        mid = distance*4/5
        while current < distance:
            if current < mid:
                # 加速度越小,单位时间内的位移越小,模拟的轨迹就越多越详细
                a = 2
            else:
                a = -3
    
            # 初速度
            v0 = v
            # 0.3秒内的位移
            s = v0*t+0.5*a*(t**2)
            # 当前的位置
            current += s
            # 添加到轨迹列表
            tracks.append(round(s))
            # 速度已经达到v,该速度作为下次的初速度
            v = v0 + a*t
        return tracks
        # tracks: [第一个0.3秒的移动距离,第二个0.3秒的移动距离,...]
    
    
    # 1、打开豆瓣官网 - 并将窗口最大化
    browser = webdriver.Chrome()
    browser.maximize_window()
    browser.get('https://www.douban.com/')
    
    # 2、切换到iframe子页面
    login_frame = browser.find_element_by_xpath('//*[@id="anony-reg-new"]/div/div[1]/iframe')
    browser.switch_to.frame(login_frame)
    
    # 3、密码登录 + 用户名 + 密码 + 登录豆瓣
    browser.find_element_by_xpath('/html/body/div[1]/div[1]/ul[1]/li[2]').click()
    browser.find_element_by_xpath('//*[@id="username"]').send_keys('15110225726')
    browser.find_element_by_xpath('//*[@id="password"]').send_keys('zhanshen001')
    browser.find_element_by_xpath('/html/body/div[1]/div[2]/div[1]/div[5]/a').click()
    time.sleep(4)
    
    # 4、切换到新的iframe子页面 - 滑块验证
    auth_frame = browser.find_element_by_xpath('//*[@id="TCaptcha"]/iframe')
    browser.switch_to.frame(auth_frame)
    
    # 5、按住开始滑动位置按钮 - 先移动180个像素
    element = browser.find_element_by_xpath('//*[@id="tcaptcha_drag_button"]')
    # click_and_hold(): 按住某个节点并保持
    ActionChains(browser).click_and_hold(on_element=element).perform()
    # move_to_element_with_offset(): 移动到距离某个元素(左上角坐标)多少距离的位置
    ActionChains(browser).move_to_element_with_offset(to_element=element,xoffset=180,yoffset=0).perform()
    
    # 6、使用加速度函数移动剩下的距离
    tracks = get_tracks(28)
    for track in tracks:
        # move_by_offset() : 鼠标从当前位置移动到某个坐标
        ActionChains(browser).move_by_offset(xoffset=track,yoffset=0).perform()
    
    # 7、延迟释放鼠标: release()
    time.sleep(0.5)
    ActionChains(browser).release().perform()
    

Fiddler抓包工具

  • 配置Fiddler

    1】Tools -> Options -> HTTPS
        1.1) 添加证书信任:  勾选 Decrypt Https Traffic 后弹出窗口,一路确认
        1.2) 设置之抓浏览器的包:  ...from browsers only
    
    【2】Tools -> Options -> Connections
        2.1) 设置监听端口(默认为8888)
    
    【3】配置完成后重启Fiddler('重要'3.1) 关闭Fiddler,再打开Fiddler
    
  • 配置浏览器代理

    1】安装Proxy SwitchyOmega谷歌浏览器插件
    
    【2】配置代理
        2.1) 点击浏览器右上角插件SwitchyOmega -> 选项 -> 新建情景模式 -> myproxy(名字) -> 创建
        2.2) 输入  HTTP://  127.0.0.1  8888
        2.3) 点击 :应用选项
        
    【3】点击右上角SwitchyOmega可切换代理
    
    【注意】: 一旦切换了自己创建的代理,则必须要打开Fiddler才可以上网
    
  • Fiddler常用菜单

    1】Inspector :查看数据包详细内容
        1.1) 整体分为请求和响应两部分
        
    【2】Inspector常用菜单
        2.1) Headers :请求头信息
        2.2) WebForms: POST请求Form表单数据 :<body>
                       GET请求查询参数: <QueryString>
        2.3) Raw : 将整个请求显示为纯文本
    

移动端app数据抓取

  • 方法1 - 手机 + Fiddler

    设置方法见文件夹 - 移动端抓包配置
    
  • 方法2 - F12浏览器工具

有道翻译手机版破解案例

import requests
from lxml import etree

word = input('请输入要翻译的单词:')

post_url = 'http://m.youdao.com/translate'
post_data = {
  'inputtext':word,
  'type':'AUTO'
}

html = requests.post(url=post_url,data=post_data).text
parse_html = etree.HTML(html)
xpath_bds = '//ul[@id="translateResult"]/li/text()'
result = parse_html.xpath(xpath_bds)[0]

print(result)
posted @ 2020-06-10 09:10  野哥李  阅读(13)  评论(0编辑  收藏  举报  来源