聚焦式爬虫

[toc]

聚焦爬虫

  • 概述: 爬取页面中指定的页面内容

  • 编码流程

    1. 指定url

    2. 发起请求

    3. 获取响应数据

    4. 数据解析

    5. 持久化存储

1. 数据解析

1.1 数据解析分类

  • 正则

  • bs4

  • xpath(主要)

1.2 数据解析原理

  • 概述:

    • 解析的局部文本内容都会在标签之间或者标签对应的属性中进行存储

  • 方法:

    1. 进行指定标签的定位

    2. 标签或者标签对应的属性中存储的数据值进行提取(解析)

2. 正则解析

2.1 正则表达式

  • 正则:用来匹配字符串的一门表达式语言

2.2 常用正则表达式

正则

2.2 实战之暴走漫画

bs4解析

  • 只能在python用

  • bs4数据解析原理

    • 实例化一个BeautifulSoup对象,并且将页面源码数据加载到该对象中

    • 通过调用BeautifulSoup对象中相关的属性或者方法进行标签定位和数据提取

  • 环境安装:

    • pip install bs4

    • pip install lxml

  • 如何实例化BeautifulSoup对象

    • from bs4 import BeautifulSoup

    • 对象实例化

      1. 将本地的HTML文档中的数据加载到该对象中

      1. 将互联网上获取的页面源码加载到该对象中

        • 与第一种差不多,只要先把爬取到的全部数据存到本地文档在解析

  • 提供的用于数据解析解析的属性和方法:

    • soup.tagName:返回html中第一次出现的tagName标签

    • soup.find('tagName'):返回第一次出现的tagName对应的标签

      • 属性定位:

        • soup.find('tagName',class_/id/attr='')

    • soup.find_all('tagName'):返回所有出现的tagName对应的标签(列表)

    • soup.select("某种选择器"):返回一个列表

    • soup.select("某种选择器>某种选择器 某种选择器"):>表示一个层级,空格表示多个层级

    • 获取标签中的文本数据

      • soup.a.text/string/get_text()

        • soup.a.text/get_text():获取一个标签里的所有文本内容

        • soup.a.string:获取一个标签直系的文本内容

      • 获取标签中的属性值

        • soup.a['href']

xpath解析

  • 最常用切最便捷高效的一种方式

  • xpath解析原理:

    1. 实例化一个etree的对象,且需要将被解析的页面源码数据加载到该对象中

    2. 调用etree对象中的xpath方法结合xpath表达式实现标签的定位和内容的捕获

  • 环境安装

    • pip install lxml

  • 如何实例化一个etree对象

    1. 导包:from lxml import etree

    2. 将本地的HTML文档中的数据加载到该对象中:

      • etree.parse(filePath,etree.HTMLParser())

      • 解析本地本件第二个参数最好加上,不然可能报错

    3. 可以将互联网上获取的源码数据加载到该对象中

      • etree.HTML('page_text')

  • xpath('xpath表达式')

    • 标签定位:

      • xpath表达式只能用层级定位定位标签

    • 多层级定位

    • 精准定位

    • 索引定位

    • 取直系文本

    • 取非直系文本

    • 取属性值

    • 以上所有xpath方法返回的都是列表

xpath实战之爬取58二手房

xpath实战之4k图片解析下载

xpath实战之全国城市名称爬取

xpath实战之图片爬取

网站验证码

  • 反爬机制:验证码。识别验证码图片中的数据,用于模拟登录操作

  • 识别验证码的操作:

    • 人工肉眼识别(不推荐)

    • 第三方自动识别(推荐)

      • 超级鹰:http://www.chaojiying.com/demo.html

超级鹰使用

模拟登录

  • 爬取某些用户的相关信息

  • 点击登录后会发起一个post请求

  • post请求会携带相关信息,如果参数正确就能进行模拟登录

  • 获取的页面请求返回的对象status_code属性值如果是200的话就模拟登录成功

  • http/https特性:无状态

  • 没有得到基于第二次请求的个人页面,服务器并不知道该请求是基于登录状态下的请求

  • 需要cookie存储状态

  • cookie:用来让服务器端记录客户端的相关状态

  • 不推荐使用手动cookie:通过抓包工具获取cookie值,在封装到headers中

  • 自动cookie:

    • cookie值哪里来?

      • 模拟登录post请求后,由服务器创建

    • session会话对象:

      • 可以进行请求的发送

      • 如果请求过程中产生了cookie,则该cookie会被自动存储/携带在该对象中

      • 使用session对象进行模拟登录post请求的发送(cookie就会被存储在session中)

      • session=requests.Session()

      • session对象对个人页面对应的get请求进行发送

代理理论

  • 反爬封ip:同一ip访问过多会封ip

  • 代理:代理服务器

  • 代理的作用:

    • 可以突破自身ip访问的限制

    • 可以隐藏自身真实ip

  • 相关代理网站:

    • 快代理

    • 西祠代理

    • www.goubanjia.com

  • 代理ip类型

    • http:只能应用于http协议的url

    • https:只能应用于https协议的url

  • 代理ip的匿名度:

    • 透明:服务器知道该次请求使用了代理,也知道请求对应的真实ip

    • 匿名:知道使用了代理,不知道真实ip

    • 高匿:不知道使用了代理,更不知道真实ip

  • 实现:

    • 在请求中的proxies参数中输入代理ip就行

    • 代理ip

异步爬虫

  • 目的:在爬虫中使用异步实现

  • 实现方式:

    1. 多进程,多线程(不建议)

      • 好处:可以为相关阻塞单独开启线程或者进程,阻塞操作就可以异步执行

      • 弊端:无法无限制开启多线程或者多进程

    2. 进程池:(适当使用)

      • 好处:可以减低系统对进程创建和销毁的一个频率,从而很好的减低系统的开销

      • 弊端:进程池线程或进程的数量是有限的

      • 实例:

    3. 单线程+异步协程(推荐)

    • event_loop:事侏循环,相当于一个无限循环,我们可以把一些函数注册到这个事件循环上,当满足某些条件的时候,函数就会被循环执行。

    • coroutine:协程对象,我们可以将协程对象注册到事件循环中,它会被事件循环调用。我们可以使用async 关键字来定义一个方法,这个方法在调用时不会立即被执行,而是返回一个协程对象。

    • task:任务,它是对协程对象的进一步封装,包含了任务的各个状态。

    • future:代表将来执行或还没有执行的任务,实际上和task没有本质区别.

    • async定义一个协程.

    • await用来挂起阻塞方法的执行。

    • 协程用法:

    • 协程实例:

    • 协程aiohttp模块

      • 模块安装:pip install aiohttp

      • 实现异步爬虫

selenium模块

  • 为什么需要使用selenium模块?

    • selenium可以更快捷的获取网站中动态加载的数据

    • 便捷的实现模拟登录

  • 什么是selenium模块?

    • 基于浏览器自动化的一个模块

  • selenium使用

    • 环境安装:pip install selenium

    • 下载一个浏览器的驱动程序

      • https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/(edge浏览器)

      • 可以自己查找对应浏览器的驱动下载网站

    • 实例化一个selenium对象

    • 编写浏览器自动化代码

    • 初始用

    • 相关基础语法

      • 发起请求:get()

        • 在selenium对象发送请求时的url必须带上超文本协议前缀

      • 标签定位:find系列方法

      • 标签交互:send_keys('xxx')

      • 执行js程序:excut_script('就js代码')

      • 前进、后退:forward()、back()

      • 关闭浏览器:quit()

    • 实战之操纵淘宝

  • selenium处理iframe以及动作链

    • 如果定位的标签在iframe中则必须要使用switch_to.frame('id')

    • 动作链(拖动):from selenium.webdriver import ActionChains导入动作链包

      • 实例化一个动作链对象

        • action=ActionChains(bro)

      • 触发长按且点击操作

        • action.click_and_hold(div)

      • 进行拖动

        • action.move_by_offset(17,10)

      • 动作立即执行

        • perform()

      • 释放动作链

        • action.release()

    • 实操:

    • 模拟登录

    • 实战之QQ空间登录

    • 无头浏览器和规避检测

scrapy框架

  • 什么是框架?

    • 就是一个集成了很多功能并且具有很强通用性的一个项目模板

  • 如何学习框架?

    • 什么是scrapy?

    • 爬虫中封装好的一个明星框架

    • 高性能的持久化存储

    • 异步的数据下载

    • 高性能的数据解析

    • 分布式

  • 如何安装scrapy框架?

    • mac or linux:pip install scrapy

    • windows:pip install scrapy

  1. 创建工程

    • scrapy startproject [工程名]

  2. 在spiders子目录中创建一个爬虫文件

    • 必须进入工程文件

    • scrapy genspider [爬虫文件名] [初始url]

    • 初始url必须要写

  3. 执行工程

    • scrapy crawl [爬虫文件名]

  4. 显示指定类型的日志文件

    • 在配置文件settings.py中加上,LOG_LEVEL='ERROR'

    • 查看指定错误的日志文件才显示

  5. 设置不遵守爬虫协议

    • 在配置文件中ROBOTSTXT_OBEY 默认为true,遵守爬虫协议,更改为False

scrapy数据解析

scrapy持久化存储

基于终端指令

  • 要求:只可以将parse方法的返回值存储到本地的文本文件中

  • 指令:scrapy crawl [爬虫文件名] -o [文件路径]

  • 这种持久化存储方式只能存储['json', 'jsonlines', 'jl', 'csv', 'xml', 'marshal', 'pickle']文件格式

  • 优点:简介高效便捷

  • 缺点:局限性比较强(数据只能存储到指定后缀文件中)

基于管道

  • 编码流程:

    1. 数据解析

    2. 在item类中定义相关属性(items.py文件中的类中用name=scrapy.Field()定义属性)

    3. 将解析的数据封装存储到item类型的对象

    4. 将item类型的对象交给管道进行持久化存储的操作(pipelines.py文件)

    5. 在管道类的process_item方法中要将其接受到的item对象中存储的数据进行持久化存储操作

    6. 在配置文件中开启管道(ITEM_PIPELINES = { 'shuju.pipelines.ShujuPipeline': 300, }注释解除)

    • 数值300是优先级,数值越小优先级越高

    • 好处:通用性强

    • 管道文件中一个管道类对应将一组数据存储到一个平台或载体中,在管道文件中加入一个管道类在设置文件中也要相应加入管道类设置

    • 在管道文件的process_item方法中最好带上返回值,优先级别高的管道类接收item数据后会把返回值传递给下一个管道类

全站数据爬取

  • 对一个网站所有的页码对应的页面数据进行爬取

  • 实现方式:

    1. 将所有页码url添加到start_urls列表(比较呆板)

    2. 自动手动进行请求发送(推荐)

五大核心组件

  • 调度器(包含过滤器,队列)

    • 使用过滤器对url进行去重

    • 用来接受引擎过来的请求,例如队列中,并在引擎再次请求的时候返回,可以想象成一个url(抓取网页的网址)的优先队列,由它来决定下一个要抓取的网址是什么,同时取出重复网址

  • 管道

    • 负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体,验证实体的有效性,清楚不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并进过几个特定的次序处理数据

  • 引擎

    • 用来处理整个系统的数据流处理,触发事物(框架核心)

  • 下载器

    • 用于下载网页内容,并将网页内容返回给蜘蛛(scrapy下载器是建立在twisted这个高效的异步模型上的)

  • spider

    1. 产生url

    2. 进行数据解析

    3. 爬虫是主要干活的,用于从特定的网页中提取自己需要的信息,即所谓的实体(item)。用户也可以从中提取出链接,让scrapy继续抓取下一个页面

image-20220808153912625

请求传参

  • 使用场景:

    • 如果要爬取解析的数据不在同一张页面中。(深度爬取)

    • 传递参数传递的是item对象

    • 在Request函数中使用meta参数进行参数传递

图片爬取值ImagesPipeline类

  • 基于scrapy爬取字符串类型的数据和爬取图片类型的数据区别:

    • 字符串:只需要基于xpath今夕解析且提交管道进行持久化存储

    • 图片:xpath解析除图片src的属性值。单独的对图片地址发起请求获取图片二进制类型的数据

  • 基于ImagesPipeline类:

    • 只需要将img的src的属性值进行解析,提交到管道,管道就会对图片的src进行请求发送获取图片的二进制类型的数据,还会进行持久化存储

  • 需求:爬取二次元网站的cos图片

  • 使用流程:

    1. 数据解析(图片的地址)

    2. 将存储图片地址的item提交到制定的管道类

    3. 在管道文件中自定一个基于ImagesPipeLine的一个管道类,并重写三个方法

      1. get_media_requests:根据图片地址进行图片数据的请求

      2. file_path:指定图片的存储路径

      3. item_completed:把item返回给下一个即将被执行的管道类

    4. 在配置文件中配置图片下载路径

中间件

主要有爬虫中间件与下载中间件(重点)

下载中间件:处于下载器和引擎之间。

  • 作用:可以批量拦截整个工程中发起的所有的的请求和响应

  • 拦截请求:

    • UA伪装

    • 代理IP

  • 拦截响应:

    • 篡改响应数据,响应对象

  • 使用中间件记得在设置文件中开启对应的设置

  • 拦截请求

  • 拦截响应对象

CrawlSpider类

CrawlSpider类:spider的子类,专门用作全站数据的爬取

  • 全站数据爬取方式:

    1. 基于spider:手动请求

    2. 基于crawlspider

  • crawl的使用:只有创建爬虫文件时有所不同

    • scrapy genspider -t crawl 文件名 url

    • 链接提取器(LinkExtractor):根据指定规则(allow='正则')进行指定链接的提取

    • 规则解析器(Rule):将链接提取器提取到的链接进行指定规则的解析操作

scrapy设置文件

  1. 设置日志等级

  2. 设置是否遵守爬虫协议

  3. 设置开启管道

  4. 设置图片存储路径

  5. 设置开启下载中间件

分布式爬虫

  • 概念:需要搭建一个分布式的机群,让其对一组资源进行分布联合爬取

  • 作用:提升爬取数据的效率

  • 如何实现分布式?

    • 安装scrapy-redis的组件

    • 原生的scrapy不可以实现分布式爬虫,必须要让scrapy结合scrapy-redis组件一起实现分布式爬虫

      • 调度器不可以被分布式机群共享

      • 管道不可以被分布式机群共享

    • scrapy-redis组件作用:

      • 可以给原生的scrapy框架提供可以被共享的管道和调度器

    • 实现流程

      1. 创建一个工程

      2. 创建一个基于CrawlSpider的爬虫文件

      3. 修改当前爬虫文件:

        1. 导包:from scrapy_redis.spider import RedisCrawlSpider,并且把爬虫类的父类改成RedisCrawlSpider

        2. 将start_urls和allowed_domains进行注释

        3. 添加redis_key = 'baidu'属性,为可以被共享的调度器队列的名称

        4. 编写数据解析相关操作

      4. 修改配置文件

        1. 指定可以被共享的管道

        2. 指定调度器

        3. 指定redis服务器

      5. redis相关操作配置

        1. 配置redis的配置文件

          1. 把默认绑定bind注释掉:否则只能自己电脑能访问

          2. 关闭保护模式:protected-mode:no:否则其他电脑访问只能读数据,不能写数据

        2. 结合配置文件开启redis服务

          1. redis-server 配置文件

        3. 启动客户端

          1. redis-cli

      6. 执行工程:scrapy runspider [爬虫源文件名称]

      7. 向调度器的队列中放入起始url

        • 调度器的队列在redis的客户端中

          • lpush [队列名称] [起始URL]

关于开发者工具与页面源代码不同

  • 有的网站反爬会把某些数据动态加载,这时候我们爬不到自己想要的页面,这时候我们可以读取页面源代码获取我们想要的数据

  • 可以通过抓包工具判断是否为动态加载的数据,再决定是否使用selenium模块获取动态数据也可以

关于一次获取多个xpath数据

  • xpath语句中可以用'|'符号分隔以获取多个xpath语句的属性

关于中文乱码解决方案

多页面爬取

  • post请求:在参数中有页数参数,通过修改可以改变页面

  • get请求:url参数中有页面参数,通过修改可以改变页面

最后更新于