爬虫学习心得

requests

 

一、get请求:

        网页数据是url直接加载出来的,一般是没有数据跟随的

requests.get(url= url, params= params, hearders= hearders)

其中url就是请求url的地址,如果url地址后缀是跟随用户参数的,就使用params进行用户参数的拾取,headers就是UA防伪

二、pos请求:

        网页数据是阿贾克斯请求,即数据的更新不会改变url,一般会跟随数据,进行响应页面显示

requests.post(url= url, data= data, headers= headers)

其他都一样,data就是需要跟随的数据

数据解析

一、正则

        此处略过

二、bs4

        from bs4 import BeautifulSoup

        -对象的实例化:

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

                        fb = open("./test.html", "r", encoding="utf-8")

                        soup = BeautifulSoup(fp, "lxml")

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

                        page_text = response.text

                        soup = BeautifulSoup(page_text, "lxml")

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

                -soup.tagName: 返回的是文档中第一次出现的tagName对应的标签

                -soup.find():

                                -find("tagName") : 等同于soup.tagName

                                -属性定位:

                                        -soup.find("div", class_/id/attr="song")

                -soup.find_all("tagName"): 返回一个符合要求的所有标签的列表

        -select:

                -select("某种选择器(id, class, 标签 . . . 选择器)"),返回一个列表

                -层级选择器:

                        - soup.select(" . tang > ul > li > a "): > 表示的是一个层级

                        - soup.seleect(" . tang > ul a "):空格表示的是多个层级

        -获取标签之间的文本数据:

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

                        -text / get_text(): 可以获取某一个标签总所有的文本内容,即使不属于直系

                        -string():只可以获取该标签直系的文本内容

        -获取标签中属性值:

                -soup.a["href"]

 三、xpth解析

        最常用且最便捷高效的一种解析方式,通用

        - xpath解析原理:

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

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

        - 环境的安装:

                - pip install lxml

        - 如何实例化一个etree对象: from lxml import etree

                -1.将本地的html文文档中的源码数据加载到etree对象中:

                        etree.parse(filePath)

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

                        etree.HTML("page_text")

        - xpath表达式

                - / : 表示的是从根节点开始定位。表示的是一个层级

                - //: 表示的是多个层级。可以表示从任何位置定位

                - 属性定位://div[@class="song"] 

                - 多属性定位://div[@class='song' and @name='d']

                - 索引定位://div[@class="song"]/p[3]  索引是从1开始计算的

                - 文本定位://*[text()='新闻']

                - 常用函数

                        - contains://*[contains(@class,"新")]

                                            //*[contains(text(), "新")]

                - 取文本:

                        - /text(): 获取的是标签中直系的文本内容

                        - //text(): 获去的是标签中非直系的文本内容(所有的文本内容)

                - 取属性:

                        - /@attrName 

                 - 伪元素:有些特定数据是在调用页面的时候才会进行接口通信生成,常见于下拉

                                   列表

                        - :: defore ::

                        - :: after ::

                        - 定位伪元素: 通过cssselector(直接复制页面中的文本)

验证码识别

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

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

        - 云打码:http://www.yundama.com/demo.html

 - 云打码的使用流程:

        - 注册:普通和开发者用户

        - 登录:

                - 普通用户的登录:查询该用户是否还有剩余的积分

                - 开发者用户的登录:

                        - 创建一个软件: 我的软件》添加新软件》录入软件名称》提交(软件id和秘钥)

                        - 下载示例代码:开发文档》点此下载: 云打码接口DLL》pythonHTTP示例下载

 - 超级鹰使用流程同上

实战:识别古诗文网登录页面中的验证码。

使用打码平台识别验证码的编码流程:

        - 将验证码图片进行本地下载

        - 调用平台提提供的实例代码进行图片数据识别

模拟登陆

         - 爬取基于某些用户的用户信息

需求:对人人网进行模拟登陆

        - 点击登陆按钮后会发起一个post请求

        - post请求中会携带登陆之前录入的登陆信息(用户名,密码,验证码。。。)

        - 验证码:每次请求都会变化

需求:登陆完后,爬取当前用户的相关用户信息(个人主页中显示的用户信息)

        -http/https协议特性:无状态

        - 没有请求到对应页面数据的原因:

                - 发起的第二次基于个人主页页面请求的时候,服务器端并不知道此请求是基于登

                  陆状态下的请求

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

                        - 手动处理:通过抓包工具获取cookie值,将该值封装到headers中

                        - 自动处理:

                                - cookie值的来源是哪里?

                                        - 模拟登陆post请求后,由服务器端创建

                                session会话对象:

                                        - 作用:

                                                1.可以进行请求的发送

                                                2.如果请求过程中产生了cookie,则该cookie会被自动存储/携

                                                    带在该session对象中

                                - 创建一个session对象:session = request.Session()

                                - 使用session对象进行模拟登陆post请求的发送(cookie会被存储在

                                 session中)

                                - session对象对个人主页对应的get请求进行发送(携带了cookie)

 代理

破解封IP这种反扒机制

什么是代理:

        - 代理服务器

代理的作用:

        - 突破自身IP访问的限制

        - 隐藏自身真是IP

代理的相关网站

        - 快代理

        - 西祠代理

        - www.goubanjia.com

代理IP的类型

        - http:应用到http协议对应的url中
        -https:应用到https协议对的url中

代理IP的匿名度:

        - 透明:服务器知道本机ip,也知道使用了代理IP

        - 匿名:服务器不知道本机IP,但知道代理了IP

        - 高匿:服务器不知道代理了IP

 高性能异步爬虫

目的:

        在爬虫中使用异步实现高性能的数据爬取操作

异步爬虫方式:

        - 多线程,多进程(不建议):

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

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

        - 线程池、进程池:(适当的使用)

                好处:我们可以降低系统对进程或者线程创建和销毁的评率,从而很好的降低系统

                           开销

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

单线程+异步协程(推荐):

        event_loop:事件循环,相当于一个无线循环,我们可以把一些函数注册到这个事件循环

                           上,当满足某些条件时,函数就会被循环执行

        coroutine:协程对象,我们可以将协程对象注册到事件循环中,他会被事件循环调用。我

                        们可以使用async关键字来定义一个方法,这个方法在调用时不会立即被执

                        行,而是返回一个协程对象。

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

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

        async:定义一个协程

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

selenium模块的基本使用

问题:selenium模块和爬虫之间具有怎样的关联?

        - 便捷的获取网站中动态加载的数据        

        - 便捷实现模拟登陆

什么是selenium模块?

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

selenium使用流程:

        - 环境安装:pip install selenium

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

                - google下载地址: http://chromedriver.storage.googleapis.com/index.html

                - google查看驱动和浏览器版本的映射关系:(最新版本无需查找)

                        http://blog.csdn.net/huilan_same/article/details/51896672

         - 实例化一个浏览器对象

                - from selenium import webdriver

                - # 实例化一个浏览器对象(传入浏览器驱动)

                - bro = webdriver.Chrome(executable_path='./chromedriver')

         - 编写基于浏览器自动化的操作代码

                - 发起请求:bro.get("http://baidu,com")

                - 标签定位:find_element()

                - 标签交互:send_keys()

                - 执行js程序:execute_script("jsCode")

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

                - 关闭浏览器:quit()

                - 获取浏览器当前页面的页面源码数据:page_source

          -  selenium处理iframe

                - 如果定位的标签存在于iframe标签之中,则必须使用switch_to.frame(id)

                - 动作链(拖动):from selenium.webdriver import ActionChains(driver)

                        - 实例化一个动作链对象:action = ActionChains(driver)

                        - 点击并长按操作:click_and_hold(ele)

                        - 移动步长:move_by_offset(ele)

                        - 让动作链立即执行:perform()

                        - 释放动作链对象:action.release()

HTML基础:

        - 所有的元素定位归根结底都是在静态页面的操作下实现的

        - HTML叫做标签语言,基于不同的标签来展示不同的内容

        - 常见的标签:

                - a : 超链接

                - img: 图片

                - input: 输入框、文件上传、按钮

                - iframe: 窗体

                - span、div

        - HTML标签内容,像变量名称一样是随意的,区分元素的类别主要通过class属性

        - 标签包含的属性:

                - 标签名称,所有的标签都一定会有标签名

                - 属性,单个标签可以有多个属性,只有在<>中的才是属性

                        - <a>...</a>

                        - <a/>

                - 文本,在<> </>之间的内容,叫做文本

元素定位:

        - 提供有八种不同的元素定位方法。在Selenium的实现中,准确来说是有十六种不同的

          定位方法。(8中单数,8中复数)

        - 八种元素定位:

                - id:基于标签的id属性来进行定位,类似于身份证,基本不会重复(可以提前校验

                         一下)

                - name:类似于省份证上的名字,容易重名

                - link text:用于定位超链接(a标签)(a标签的文本)

                - partial link text:定位a标签,通过模糊查找的形式来定位,类似于mysql中的like

                                            一般会有多元素的结果,一般可以通过find elements来进行定位

                                                - 不加s进行定位,默认返回查找的第一个元素

                                                - 加s进行定位,基于下标的选择返回

                - tagname:都是基于复数的s来定位,一般不推荐

                - classname :极其不推荐使用      

                - cssselector:定位届的万金油之一,专治IE浏览器下的元素定位(不支持xpath)

                - xpath

        - 最为主流的定位方法是xpath,最灵活的定位方法是cssselector、xpath

 12306登陆

- 超级鹰:用户登录-超级鹰验证码识别代答题平台

        - 注册:普通用户

        - 登陆:普通用户

                - 题分查询:重置

                - 创建一个软件(id)

                - 下载示例代码

- 12306模拟登陆编码流程:

        - 使用selenium打开登陆界面

        - 对当前selenium打开的这张页面进行截图

        -  对当前图片局部区域(验证码图片)进行裁剪

                - 好处:将验证码图片和模拟登陆进行一一对应(因为图片会刷新)

        - 使用超级鹰识别验证码图片(坐标)

scrapy框架

- 什么是框架?

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

-如何学习框架?

        - 专门学习框架封装的各种功能的详细用法

- 什么是scrapy?

        - 爬虫中封装好的一个明星框架 。功能:高性能的持久化操作,异步的数据下载,高性

                                                                        能的数据解析、分布式

- scrapy框架的基本使用

        - 环境的安装:

                - mac or linux:pip install scrapy

                - windows:

                        - 实测可直接安装

- 创建一个工程:scrapy startproject xxx1

- cd xxx1

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

        - scrapy genspider xxx2 www.xxx.com

- 执行工程:

        - scrapy crawl xxx2

- scrapy数据解析

- scrapy持久化存储

        - 基于终端指令:

                - 指令:scrapy crawl xxx2 -o filepath

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

                - 注意:持久化存储对应的文本文件的类型只可以为:'json','jsonlines','jl','csv','xml'

                - 好处:简洁高效便捷

                - 确定:局限性大(数据只可以存储到指定后缀的文本文件中)

        - 基于管道:

                - 编码流程:

                        - 数据解析

                        - 在item类中定义相关的属性   

title = scrapy.Field()
content = scrapy.Field()

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

item["title"] = poetry_title
item["content"] = poetry_text

                        - 将item类型的对象提交给管道进行持久化存储的操作

yield item

                        - 在管道类的process_item中要将其接收到的item对象中存储的数据进行持久

                          化存储操作

class GushiPipeline:
    fp = None
    # 重写其中的一个父类方法:该方法只在开始爬虫的时候被调用一次
    def open_spider(self, spider):
        print('开始打印。。。')
        self.fp = open('./存储.text', "w", encoding="utf-8")
    # 专门用来处理item类型对象
    # 该方法可以接收爬虫文件提交过来的item对象。
    # 该方法每接收到一个item就会被调用一次
    def process_item(self, item, spider):
        title = item["title"]
        content = item["content"]
        self.fp.write(title + ":" + content)
        return item

    def close_spider(self, spider):
        print("结束打印!")
        self.fp.close()

                        - 在配置文件中开启管道

ITEM_PIPELINES = {
   'GuShi.pipelines.GushiPipeline': 300,
    # 300表示的是优先级,数值越小优先级越高
}

        - 好处:通用性强。

面试题:将爬取到的数据一份存储到本地,一份存储到数据库,如何实现?

重点:

        - 管道文件中的一个管道类对应的是将数据存储到一种平台

        - 爬虫文件提交的item只会给管道文件中第一个被执行的管道类接收

        - process_item中的return item表示将item传递给下一个即将被执行的管道类

spiders文件:

import scrapy
from GuShi.items import GushiItem

class GushiSpider(scrapy.Spider):
    name = 'gushi'
    # allowed_domains = ['www.xxx.com']
    start_urls = ['https://so.gushiwen.cn/shiwens/']

    # 基于终端指令的存储方式
    # def parse(self, response):
    #     # 解析:诗词的标题+内容
    #     # xpath返回的是列表,且列表元素一定是selector类型的对象
    #     # extract可以将selector对象中的data参数存储的字符串提取出来
    #     poetry_div_list = response.xpath('.//div[@id="leftZhankai"]//div[@class="sons"]')
    #     content = []
    #     for poetry in poetry_div_list:
    #         poetry_title = poetry.xpath("./div[1]/p[1]//b/text()")[0].extract()
    #         poetry_text = poetry.xpath("./div[1]/div[2]/text() | ./div[1]/div[2]//p/text()").extract()
    #         poetry_text = ''.join(poetry_text)
    #         dict = {"title": poetry_title,
    #                 "content": poetry_text}
    #         content.append(dict)
    #     return content
    # ============================================================================================
    def parse(self, response):
        poetry_div_list = response.xpath('.//div[@id="leftZhankai"]//div[@class="sons"]')
        content = []
        for poetry in poetry_div_list:
            poetry_title = poetry.xpath("./div[1]/p[1]//b/text()")[0].extract()
            poetry_text = poetry.xpath("./div[1]/div[2]/text() | ./div[1]/div[2]//p/text()").extract()
            poetry_text = ''.join(poetry_text)
            item = GushiItem()
            item["title"] = poetry_title.replace(' ', '').strip() + '====='
            item["content"] = poetry_text.replace(' ', '').strip()
            # 将item提交给管道
            yield item

items文件

import scrapy


class GushiItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    title = scrapy.Field()
    content = scrapy.Field()
    # pass

piplines文件

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html


# useful for handling different item types with a single interface
from itemadapter import ItemAdapter
import pymysql

class GushiPipeline(object):
    fp = None
    # 重写其中的一个父类方法:该方法只在开始爬虫的时候被调用一次
    def open_spider(self, spider):
        print('开始打印。。。')
        self.fp = open('./存储.txt', "w", encoding="utf-8")
    # 专门用来处理item类型对象
    # 该方法可以接收爬虫文件提交过来的item对象。
    # 该方法每接收到一个item就会被调用一次
    def process_item(self, item, spider):
        title = item["title"]
        content = item["content"]
        self.fp.write(title + ":" + content + '\n')
        # 最好加上return,只有这样优先级高的类才会把item对象传递给下一个即将被执行的管道类
        return item

    def close_spider(self, spider):
        print("结束打印!")
        self.fp.close()

# 管道文件中一个管道类对应将一组数据存储到一个平台或者载体中
class mysqlPipleLine(object):
    conn = None
    cursor = None
    def open_spider(self,spider):
        self.conn = pymysql.Connect(host='127.0.0.1',port=3306,user='root',password='123456',db='test2',charset='utf8')
    def process_item(self, item, spider):
        self.cursor = self.conn.cursor()
        try:
            self.cursor.execute('insert into python values("%s","%s");' % (item["title"], item["content"]))
            self.conn.commit()
        except Exception as e:
            print(e)
            print('错误')
            self.conn.rollback()
        return item
    def close_spider(self,spider):
        self.cursor.close()
        self.conn.close()

# 爬虫文件提交的item类型的对象最终会提交给优先级高的管道类

基于Spider的全站数据爬取

就是将网站中某板块下的全部页码对应的页面数据进行爬取

需求:爬取我要个性网中的照片的名称

实现方式:

        - 将所有页面的url添加到start_urls列表(不推荐)

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

                - 手动请求发送:

yield scrapy.Request(url=new_url, callback=self.parse)

# callback专门用作数据解析

五大核心组件

 请求传参

- 使用场景:如果爬取解析的数据不在同一张页面中。(深度爬取)

- 需求: 爬取我要个性网中图片名称,图片作者名称

import scrapy
from tupianPro.items import TupianproItem

class Tupian2Spider(scrapy.Spider):
    name = 'tupian2'
    # allowed_domains = ['www.xxx.com']
    start_urls = ['https://www.woyaogexing.com/tupian/dongman/index.html']

    url = 'https://www.woyaogexing.com/tupian/dongman/index_%d.html'
    page_num = 2
    # 回调函数接受item
    def detail_parse(self,response):
        author = response.xpath('//*[@id="main"]/div[3]/div[1]/div[1]/div[1]/div[1]/div/a/text()').extract_first()
        print(author)
        item = response.meta['item']
        item['author'] = author
        yield item
    # 解析图片名字
    def parse(self, response):
        div_list = response.xpath('//*[@id="main"]/div[3]/div[1]/div[2]/div')
        for div in div_list:
            item = TupianproItem()
            title = div.xpath('./a[2]/text()').extract_first()
            item['title'] = title
            print(title)
            new_url = 'https://www.woyaogexing.com/' + div.xpath('./a[1]/@href').extract_first()
            # 对详情页发送请求获取详情页源码数据
            # 手动请求发送
            # 请求传参:meta={},可以将meta字典传递给请求对应的回调函数
            yield scrapy.Request(url=new_url, callback=self.detail_parse, meta={'item': item})

            # 分页操作
            if self.page_num <= 6:
                new_url = format(self.url % self.page_num)
                self.page_num += 1
                yield scrapy.Request(url=new_url, callback=self.parse)



 图片数据爬取值ImagesPipeline

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

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

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

                     的数据

ImagesPipeline:

        - 只需要将img的src的属性值进行解析,提交到管道,管道就会对图片的src进行请求发

           送获取二进制类型的数据,且还会帮我们进行持久化存储

需求: 爬取我要个性网中的图片

使用流程:

        - 数据解析(图片的地址)

        - 在存储图地址的item提交到制定的管道类

        - 在管道文件中自定制一个基于ImagesPipeLine的一个管道类

                - get_media_request

                - file_path

                - item_completed

        - 在配置文件中:

                - 指定图片存储的目录: IMAGES_STORE = ‘./image_file’

                - 指定开启的管道:自定制的管道类

import scrapy
from meituPro.items import MeituproItem

class MeituSpider(scrapy.Spider):
    name = 'meitu'
    # allowed_domains = ['www.xxx.com']
    start_urls = ['https://www.woyaogexing.com/tupian/dongman/index.html']

    url = 'https://www.woyaogexing.com/tupian/dongman/index_%d.html'
    page_num = 2
    def parse(self, response):
        div_list = response.xpath('//*[@id="main"]/div[3]/div[1]/div[2]/div')
        for div in div_list:
            # 如果出现图片懒加载,则需要使用图片的伪属性
            src = 'https:' + div.xpath('./a/img/@src').extract_first()
            print(src)
            item = MeituproItem()
            item['src'] = src
            yield item
        if self.page_num <= 6:
            new_url = format(self.url% self.page_num)
            self.page_num += 1
            yield scrapy.Request(url=new_url, callback=self.parse)
# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html

import scrapy


class MeituproItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    src = scrapy.Field()
    # pass
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html


# useful for handling different item types with a single interface
import scrapy
from itemadapter import ItemAdapter


# class MeituproPipeline(object):
#     def process_item(self, item, spider):
#         return item
from scrapy.pipelines.images import ImagesPipeline
class imagesPipeline(ImagesPipeline):
    # 根据图片地址进行图片数据的请求
    def get_media_requests(self, item, info):
        yield scrapy.Request(item['src'])
    # 指定图片存储的路径
    def file_path(self, request, response=None, info=None, *, item=None):
        imgName = request.url.split('/')[-1]
        return imgName
    # 返回给下一个即将被执行的管道类
    def item_completed(self, results, item, info):
        return item

# Scrapy settings for meituPro project
#
# For simplicity, this file contains only settings considered important or
# commonly used. You can find more settings consulting the documentation:
#
#     https://docs.scrapy.org/en/latest/topics/settings.html
#     https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
#     https://docs.scrapy.org/en/latest/topics/spider-middleware.html

BOT_NAME = 'meituPro'

SPIDER_MODULES = ['meituPro.spiders']
NEWSPIDER_MODULE = 'meituPro.spiders'


# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36'

# Obey robots.txt rules
ROBOTSTXT_OBEY = False
LOG_LEVEL = 'ERROR'

# Configure maximum concurrent requests performed by Scrapy (default: 16)
#CONCURRENT_REQUESTS = 32

# Configure a delay for requests for the same website (default: 0)
# See https://docs.scrapy.org/en/latest/topics/settings.html#download-delay
# See also autothrottle settings and docs
#DOWNLOAD_DELAY = 3
# The download delay setting will honor only one of:
#CONCURRENT_REQUESTS_PER_DOMAIN = 16
#CONCURRENT_REQUESTS_PER_IP = 16

# Disable cookies (enabled by default)
#COOKIES_ENABLED = False

# Disable Telnet Console (enabled by default)
#TELNETCONSOLE_ENABLED = False

# Override the default request headers:
#DEFAULT_REQUEST_HEADERS = {
#   'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
#   'Accept-Language': 'en',
#}

# Enable or disable spider middlewares
# See https://docs.scrapy.org/en/latest/topics/spider-middleware.html
#SPIDER_MIDDLEWARES = {
#    'meituPro.middlewares.MeituproSpiderMiddleware': 543,
#}

# Enable or disable downloader middlewares
# See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
#DOWNLOADER_MIDDLEWARES = {
#    'meituPro.middlewares.MeituproDownloaderMiddleware': 543,
#}

# Enable or disable extensions
# See https://docs.scrapy.org/en/latest/topics/extensions.html
#EXTENSIONS = {
#    'scrapy.extensions.telnet.TelnetConsole': None,
#}

# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
   'meituPro.pipelines.imagesPipeline': 300,
}

# Enable and configure the AutoThrottle extension (disabled by default)
# See https://docs.scrapy.org/en/latest/topics/autothrottle.html
#AUTOTHROTTLE_ENABLED = True
# The initial download delay
#AUTOTHROTTLE_START_DELAY = 5
# The maximum download delay to be set in case of high latencies
#AUTOTHROTTLE_MAX_DELAY = 60
# The average number of requests Scrapy should be sending in parallel to
# each remote server
#AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0
# Enable showing throttling stats for every response received:
#AUTOTHROTTLE_DEBUG = False

# Enable and configure HTTP caching (disabled by default)
# See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings
#HTTPCACHE_ENABLED = True
#HTTPCACHE_EXPIRATION_SECS = 0
#HTTPCACHE_DIR = 'httpcache'
#HTTPCACHE_IGNORE_HTTP_CODES = []
#HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage'

# Set settings whose default value is deprecated to a future-proof value
REQUEST_FINGERPRINTER_IMPLEMENTATION = '2.7'
TWISTED_REACTOR = 'twisted.internet.asyncioreactor.AsyncioSelectorReactor'
IMAGES_STORE = '../tupian_scrapy/'

中间件

 下载中间件

        - 位置:引擎和下载器之间

        - 作用:批量拦截到整个工程中所有的请求和响应

        - 拦截请求:

                - UA伪装:process_request

                - 代理IP:process_exception:return request

        - 拦截响应:

                - 篡改响应数据、响应对象

                - 需求:爬取网易新闻中的新闻数据(标题和内容)

                        - 1.通过网易新闻的首页解析出五大板块的详情页的url(没有动态加载)

                        - 2.每一个板块对应的新闻标题都是动态加载出来的(动态加载)

                        - 3.通过解析出每一条新闻详情页的url获取详情页的页面源码,解析出内容

CrawlSpider类

 - 是Spider的一个子类

- 全站数据爬取的方式

        - 基于Spider:手动请求

        - 基于CrawlSpider

- CrawlSpider的使用

        - 创建一个工程

        - cd 新工程

        - 创建爬虫文件(CrawlSpider)

                - scrapy genspider -t crawl xxx www.xxx.com

                - 链接提取器:

                        - 作用:根据指定的规则进行指定链接的提取

                - 规则解析器:

                        - 作用:将链接提取器提取到的链接进行指定规则(callback)的解析

        # 需求:爬取秦楚论坛-十堰城事的帖子标题,帖子内容

                - 分析:爬取的数据不在同一页面中

                - 1.可以使用链接提取器提取所有页码链接

                - 2.让链接提取器提取所有的帖子详情页的链接

                        

分布式爬虫

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

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

- 如何实现分布式?

        - 安装一个scrapy-redis的组件

        - 原生的scrapy是不可以实现分布式爬虫的,必须结合scrapy_redis组件一起使用

        - 原因:

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

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

        - scrapy-redis组件作用
                - 可以给原生的scrapy框架提供可以被共享的管道和调度器

        - 实现流程

                - 创建一个工程

                - 常见一个基于CrawlSpider的爬虫文件

                - 修改当前的爬虫文件:

                        - 导包:from scrapy_redis。spiders import RedisCrawlSpider

                        - 将start_urls和allowed_domains进行注释

                        - 添加一个新属性:redis_key = 'sun' 可以被共享的调度器队列的名称

                        - 编写数据解析相关的操作

                        - 将当前爬虫类的父类修改为RedisCrawlSpider

                - 修改配置文件settings

                        - 指定可以被共享的管道:

ITEM_PIPELINES = {
        'scrapy_redis.pipelines.RedisPipeline':400
}

                        - 指定调度器:

DUPEFILTER_CLASS = 'scrapy_redis.dupefilter.RFPDupeFilter'
# 使用scrapy_redis组件自己的调度器
SCHEDULER = 'scrapy_redis.scheduler.Scheduler'
# 配置调度器是否要持久化,也就是爬虫结束了,需不需要清空Redis中请求队列和去重指纹的set
SCHEDULER_PERSIST = True

                       - 指定redis服务器:

# 指定redis
# 默认本机:127.0.0.1
# 推荐写远程服务器的ip
REDIS_HOST = 'redis服务器的ip地址'
REDIS_PORT = 6379

                        - redis相关操作配置:

                                - 配置redis的配置文件:

                                        - linux或者mac:redis.conf

                                        - windows:redis.windows.conf

                                        - 打开配置文件进行修改:

                                                - 将bind 172.0.0.1进行删除

                                                - 关闭保护模式:protected-mode yes改为no

                                - 结合配置文件开启redis服务

                                        - redis-server 配置文件

                                - 启动客户端:

                                        - redis-cli

                                - 执行工程:

                                        - scrapy runspider 爬虫文件

                                - 向调度器的队列中放入一个起始的url:

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

                                                - lpush xxx www.xxx.com

                              - 爬取到的数据存储在了redis的proName:items这个数据结构中

增量式爬虫

- 概念:检测网站数据更新的情况,只会爬取网站最新更新出来的数据。

- 分析:

        - 指定一个起始url

        - 基于CrawlSpider获取其他页码链接

        - 基于Rule将其他页码链接进行请求

        - 从每一个页码对应的源码中解析出每一个电影详情页的url


        -  核心:检测电影详情页的url之前有没有请求过   

                - 将爬取过的电影详情页的url存储

                        - 存储到redis的set数据结构中

             

        - 对详情页的url发起请求,然后解析出电影的名称和简介

        - 进行持久化存储

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值