网络爬虫框架Scrapy的进阶使用

管道pipeline

在Scrapy中,管道(Pipeline)是一种机制,用于处理从爬虫提取的数据。管道可以对爬虫爬取到的数据进行后续处理,如验证、清洗、存储等操作。Scrapy中的管道是以Python类的形式实现的,每个管道类可以包含一系列方法,如process_item(self, item, spider)用于处理数据。

在Scrapy中,可以通过配置settings.py文件来启用、配置和排序管道,控制数据的处理流程。通过管道,可以将爬取到的数据传递给不同的处理方法,例如将数据存储到数据库、写入文件等。

要使用管道,需要在项目中的pipelines.py文件中自定义管道类,并在settings.py文件中启用并配置它。以下是配置Pipeline的一般步骤:

scss
复制代码
1.在项目的pipelines.py文件中定义管道类。

2.管道类中实现对数据的处理逻辑,通常包括process_item(self, item, spider)方法。

3.在settings.py文件中启用并配置管道,指定每个管道的顺序以及配置参数。

常用方法

pipeline中有3个常用方法:

python
复制代码
process_item(self,item,spider): 管道类中必须有的函数,其实现对item数据的处理,且必须return item

open_spider(self, spider): 在爬虫开启的时候执行一次

close_spider(self, spider): 在爬虫关闭的时候执行一次

创建数据模型Item与爬虫Spider

items.py中创建DemoItem类

python
复制代码
import scrapy

class DemoItem(scrapy.Item):
	# 标题
    title = scrapy.Field()
    # 数量
    count = scrapy.Field()

spiders目录下创建DemospiderSpider.py文件

python
复制代码
import scrapy

from scrapy_project.items import DemoItem


# 继承自爬虫类
class DemospiderSpider(scrapy.Spider):
    # 定义爬虫名称
    name = "demospider"
    # 设置允许爬取的范围
    allowed_domains = ["www.runoob.com"]
    # 设置开始爬取的请求地址
    start_urls = ["https://www.runoob.com/"]

    # 实现解析函数,提取数据或者提取URL,并提交给引擎
    def parse(self, response):
    	# scrapy的response对象可以直接进行xpath
        list = response.xpath('/html/body/div[4]/div/div[2]/div/h2/text()').extract()
        print("--------------------------------")
        index = 1
        for title in list:
            div = "div[" + str(index) + "]"
            index = index + 1
            count = response.xpath('/html/body/div[4]/div/div[2]/' + div + '/a/h4/text()').extract()

            item = DemoItem()
            item['title'] = title
            item['count'] = len(count)
            # 提交数据给引擎
            # yield能够传递的对象只能是:BaseItem, Request, dict, None
            yield item

创建多个管道pipeline

复制代码
不同的pipeline可以处理不同爬虫的数据,通过spider.name属性来区分

不同的pipeline能够对一个或多个爬虫进行不同的数据处理的操作,如一个进行数据清洗,一个进行数据的保存

同一个管道类也可以处理不同爬虫的数据,通过spider.name属性来区分
python
复制代码
import json

from pymongo import MongoClient


class DemoFilePipeline(object):
    # 爬虫开启的时候执行一次
    def open_spider(self, spider):
        print(f"爬虫: {spider.name} ,DemoFilePipeline启动。")
        if spider.name == 'demospider':
            self.f = open('demospider.txt', 'a', encoding='utf-8')

    # 爬虫关闭的时候执行一次
    def close_spider(self, spider):
        print(f"爬虫: {spider.name} ,DemoFilePipeline关闭。")
        if spider.name == 'demospider':
            self.f.close()

    def process_item(self, item, spider):
        if spider.name == 'demospider':
            self.f.write(json.dumps(dict(item), ensure_ascii=False, indent=2) + ',\n')
        return item


class DemoMongoPipeline(object):
    # 爬虫开启的时候执行一次
    def open_spider(self, spider):
        print(f"爬虫: {spider.name} ,DemoMongoPipeline启动。")
        # 不同的pipeline可以处理不同爬虫的数据,通过spider.name属性来区分
        if spider.name == 'demospider':
            # 实例化mongoclient
            con = MongoClient(host="IP", port=27017, username="test", password="123456", authSource="demo")
            # 创建数据库名为demo,集合名为test的集合操作对象
            self.collection = con.demo.test

    # 爬虫关闭的时候执行一次
    def close_spider(self, spider):
        if spider.name == 'demospider':
            print(f"爬虫: {spider.name} ,DemoMongoPipeline关闭。")

    def process_item(self, item, spider):
        if spider.name == 'demospider':
            # item对象必须是一个字典,如果此时item是BaseItem则需要先转换为字典:dict(BaseItem)
            print(type(item))
            self.collection.insert_one(dict(item))
        # 注意:不return,那么另一个权重较低的pipeline将不会获得item
        return item

开启管道

在settings.py文件中启用pipeline并配置它

DemoFilePipeline是自定义的管道类,400是指定的顺序值。较小的顺序值会优先处理数据。可以定义多个管道类,并根据需要指定顺序和配置参数。

python
复制代码
ITEM_PIPELINES = {
    # 定义具体Pipeline管道类的py文件.定义的Pipeline管道类 : 权重数值
    # 权重值越小,越优先执行
    'scrapy_project.pipelines.DemoFilePipeline': 400,
    'scrapy_project.pipelines.DemoMongoPipeline': 500, 
}

启动爬虫

python
复制代码
scrapy crawl demospider

在这里插入图片描述

配置文件

默认配置文件

default_settings.py是系统默认配置文件 在这里插入图片描述

项目配置文件

settings.py属于项目文件,可以修改以此覆盖默认配置,常用配置如下:

复制代码
USER_AGENT:设置ua

ROBOTSTXT_OBEY: 是否遵守robots协议,默认是遵守

CONCURRENT_REQUESTS: 设置并发请求的数量,默认是16个

DOWNLOAD_DELAY: 下载延迟,默认无延迟

COOKIES_ENABLED: 是否开启cookie,即每次请求带上前一次的cookie,默认是开启的

DEFAULT_REQUEST_HEADERS: 设置默认请求头

SPIDER_MIDDLEWARES: 爬虫中间件,设置过程和管道相同

DOWNLOADER_MIDDLEWARES: 下载中间件

crawlspider爬虫

CrawlSpider是Scrapy框架中的一个高级爬虫类,用于快速构建基于规则的爬虫。CrawlSpider是Spider类的一个子类,它提供了更强大的功能和灵活性,特别适用于需要按照特定规则(如链接规则、回调函数等)爬取和处理数据的场景。

CrawlSpider主要通过规则定义来确定要爬取的链接,避免手动编写多个回调函数处理链接,为爬取规则提供更简洁的方式。

crawlspider是从response中提取所有的满足规则的url地址,组装成Reuqest对象后自动发送给引擎,同时能够指定callback函数

创建crawlspider爬虫

创建crawlspider爬虫,保存在Scrapy项目的spiders目录下

python
复制代码
scrapy genspider –t crawl 爬虫名称 爬虫域名

scrapy genspider -t crawl myspider https://www.example.com
Created spider 'myspider' using template 'crawl' in module:
  demo.spiders.myspider

文件的基本结构如下:

python
复制代码
# 导入必要的库和模块
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule

# 编写CrawlSpider类:定义CrawlSpider类并设置规则和回调函数。
class MyspiderSpider(CrawlSpider):
    name = "myspider"
    allowed_domains = ["www.example.com"]
    start_urls = ["http://www.example.com/"]

    rules = (Rule(LinkExtractor(allow=r"Items/"), callback="parse_item", follow=True),)

    def parse_item(self, response):
        item = {}
        # item["domain_id"] = response.xpath('//input[@id="sid"]/@value').get()
        # item["name"] = response.xpath('//div[@id="name"]').get()
        # item["description"] = response.xpath('//div[@id="description"]').get()
        return item

核心类Rule

在crawlspider爬虫中,没有parse函数,核心重点在Rule规则对象,Rules是一个元组或者是列表,包含的是Rule对象

Rule规则对象

vbnet
复制代码
LinkExtractor 链接提取器,根据规则提取链接

callback 表示经过连接提取器提取出来的url地址响应的回调函数,可以没有,没有表示响应不会进行回调函数的处理

follow 连接提取器提取的url地址对应的响应是否还会继续被rules中的规则进行提取,True表示会,Flase表示不会

process_links: 当链接提取器LinkExtractor获取到链接列表的时候调用该参数指定的方法,这个自定义方法可以用来过滤url,且这个方法执行后才会执行callback指定的方法

LinkExtractor链接提取器

ini
复制代码
allow=() 符合正则表达式条件的链接被提取,如果为空,则全部匹配

deny=() 符合正则表达式条件的链接不被提取,优先级高于allow

allow_domains=() 符合条件的域名被提取

deny_domains=() 符合条件的域名不被提取,优先级高于allow_domains

restrict_xpaths=()  使用xpath规则进行匹配,和allow共同过滤url

tags=('a', 'area') 提取链接的标签,默认 a 和 area

attrs=('href',) 提取链接的标签的属性,默认 href

restrict_css=() 符合css选择器的链接被提取

strip=True 提取数据后进行两边去除空白

crawlspider爬虫的使用

在items.py定义Item数据模型对象

python
复制代码
class DemoItem(scrapy.Item):
    # 标题
    title = scrapy.Field()
    # 链接
    link = scrapy.Field()
    # 回复数量
    count = scrapy.Field()
    # 作者名
    author = scrapy.Field()

在spiders目录下创建Spider爬虫,Spider爬虫实现方式如下:

python
复制代码
import scrapy

from scrapy_project.items import DemoItem


class TieBaSpider(scrapy.Spider):
    name = 'tieba'
    # 检查允许的域名
    allowed_domains = ['tieba.baidu.com']
    # 置起始的url
    start_urls = ['https://tieba.baidu.com/f?ie=utf-8&kw=chatgpt']

    def parse(self, response):
        # 获取所有的帖子列表
        node_list = response.xpath('//*[@id="thread_list"]/li')
        print(len(node_list))

        # 遍历所有的帖子节点列表
        for num, node in enumerate(node_list):
            item = DemoItem()
            item['title'] = node.xpath('./div/div[2]/div[1]/div[1]/a/text()').extract_first()
            item['link'] = "https://tieba.baidu.com" + str(
                node.xpath('./div/div[2]/div[1]/div[1]/a/@href').extract_first())
            item['count'] = node.xpath('./div/div[1]/span/text()').extract_first()
            authorInfo = str(node.xpath('./div/div[2]/div[1]/div[2]/span[1]/@title').extract_first()).split(" ")
            item['author'] = authorInfo[1] if len(authorInfo) == 2 else ""

            yield item

        # 获取翻页url
        part_url = response.xpath('//a[contains(text(),"下一页>")]/@href').extract_first()

        # 拼接完整翻页url
        next_url = 'https:' + part_url
        yield scrapy.Request(url=next_url, callback=self.parse)

在spiders目录下创建crawlspider爬虫,crawlspider爬虫实现方式如下:

python
复制代码
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule

from scrapy_project.items import DemoItem


class TieBaSpider(CrawlSpider):
    name = 'tieba'
    # 检查允许的域名
    allowed_domains = ['tieba.baidu.com']
    # 置起始的url
    start_urls = ['https://tieba.baidu.com/f?ie=utf-8&kw=chatgpt']

    # https://tieba.baidu.com/f?kw=chatgpt&ie=utf-8&pn=100
    # 注意: restrict_xpaths指向元素,即包含链接的容器,而不是它的属性
    # 所以不能是://a[contains(text(),"下一页>")]/@href
    # 否则出现异常:AttributeError: ‘str‘ object has no attribute ‘iter‘
    # next_page_linkExtractor = LinkExtractor(restrict_xpaths=('//a[contains(text(),"下一页>")]'))

    # 使用正则
    next_page_linkExtractor = LinkExtractor(allow=r'&pn=\d+$')

    rules = (
        Rule(next_page_linkExtractor, callback='start_parse', follow=True),
    )

    def start_parse(self, response):
        # 获取所有的帖子列表
        node_list = response.xpath('//*[@id="thread_list"]/li')
        print(len(node_list))

        # 遍历所有的帖子节点列表
        for num, node in enumerate(node_list):
            item = DemoItem()
            item['title'] = node.xpath('./div/div[2]/div[1]/div[1]/a/text()').extract_first()
            item['link'] = "https://tieba.baidu.com" + str(
                node.xpath('./div/div[2]/div[1]/div[1]/a/@href').extract_first())
            item['count'] = node.xpath('./div/div[1]/span/text()').extract_first()
            authorInfo = str(node.xpath('./div/div[2]/div[1]/div[2]/span[1]/@title').extract_first()).split(" ")
            item['author'] = authorInfo[1] if len(authorInfo) == 2 else ""

            yield item

创建管道Pipeline

python
复制代码
class TieBaPipeline:
    # 爬虫开启的时候执行一次
    def open_spider(self, spider):
        # 不同的pipeline可以处理不同爬虫的数据,通过spider.name属性来区分
        if spider.name == 'tieba':
            # 实例化mongoclient
            con = MongoClient(host="IP", port=27017, username="test", password="123456", authSource="demo")
            # 创建数据库名为demo,集合名为test的集合操作对象
            self.collection = con.demo.tieba

    def process_item(self, item, spider):
        if spider.name == 'tieba':
            # item对象必须是一个字典,如果此时item是BaseItem则需要先转换为字典:dict(BaseItem)
            print(type(item))
            self.collection.insert_one(dict(item))
            return item

在settings.py文件中开启管道

python
复制代码
ITEM_PIPELINES = {
    # 定义具体Pipeline管道类的py文件.定义的Pipeline管道类 : 权重数值
    # 权重值越小,越优先执行
    'scrapy_project.pipelines.TieBaPipeline': 400,
}

启动爬虫

python
复制代码
scrapy crawl tieba

在这里插入图片描述

CrawlSpider去重机制

CrawlSpider中的去重机制是通过Scrapy内置的过滤重复请求的功能来实现的,主要依赖于scrapy.dupefilters.DupeFilter类,它使用一个Python set集合来保存已经爬取过的URL,这个集合会在内存中一直存在,如果爬虫需要长时间运行,会占用较多的内存。

在CrawlSpider中,默认情况下,已经使用了基于存储请求指纹的去重过滤器。这个指纹是通过对请求的URL进行哈希计算而生成的,确保同一个URL不会被重复请求。

Scrapy内置的去重过滤器可通过DUPEFILTER_CLASS设置在项目的settings.py中进行调整,常见的内置过滤器包括:

python
复制代码
scrapy.dupefilters.RFPDupeFilter(默认的去重过滤器):使用请求指纹(request fingerprint)进行去重。

scrapy.dupefilters.BaseDupeFilter:基本去重过滤器,可自定义扩展。

自定义的去重过滤器:可以根据需求实现自定义的去重机制。

如果需要更加高效的去重机制,可以使用Scrapy提供的其他去重中间件,例如:

python
复制代码
scrapy_redis.dupefilter.RFPDupeFilter: 一个基于Redis数据库实现的去重中间件,可以支持分布式爬虫

scrapy.dupefilters.BaseDupeFilter: 这是一个抽象类,可以继承这个类并自定义去重机制

在settings.py文件中通过DUPEFILTER_CLASS设置需要使用的去重中间件类

python
复制代码
DUPEFILTER_CLASS = 'scrapy_redis.dupefilter.RFPDupeFilter'

REDIS_URL = 'redis://localhost:6379'

CrawlSpider与Spider

Spider是爬虫基类,CrawlSpider是Spider的一个子类。CrawlSpider实现了一种特殊的爬取机制,可以通过定义一些规则来自动爬取多个页面,并且可以自动处理页面之间的链接关系。

与Spider相比,CrawlSpider具有以下特点:

1.自动处理链接:

CrawlSpider会自动根据规则提取页面中的链接,并自动向这些链接发送请求,以此实现自动爬取多个页面的功能。

2.规则定义:

CrawlSpider使用rules属性定义页面链接提取规则,这些规则是由Rule对象组成的元组。每个Rule对象包含一个LinkExtractor对象,用于定义链接的提取规则,以及一个callback参数,用于指定回调函数,处理从链接页面提取的数据。

3.去重机制:

CrawlSpider内置了一个去重机制,可以避免重复爬取相同的URL。默认情况下,它使用RFPDupeFilter进行URL去重。

中间件

概述

Scrapy中间件(Middleware)是一种可插入的处理组件,用于在Scrapy请求和响应处理的不同阶段进行干预和定制化处理。

中间件机制允许用户在请求发送到下载器之前或响应发送给爬虫之前对它们进行预处理或后处理。这提供了灵活性,使用户能够扩展Scrapy框架并对请求和响应进行各种类型的处理。

中间件代码存放在middlewares.py

应用场景

中间件可以用于许多场景,如添加自定义的请求头、处理异常、修改请求数据、实现代理、限制请求频率等。

修改请求和响应:

中间件可以对请求和响应进行修改,包括修改请求头、请求参数、响应内容等等。这样可以根据具体情况对请求和响应进行定制化处理,以满足爬虫需求。

过滤掉请求和响应:

中间件可以根据具体情况对请求和响应进行过滤,例如重定向、代理、Cookie 等。可以通过中间件保证请求和响应的合法性和有效性,同时降低反爬风险。

自定义扩展功能:

中间件可以实现自定义扩展功能,例如爬虫数据统计、日志记录、异常处理等。这些功能可以增加爬虫的可维护性和可扩展性。

注意:

在scrapy默认的情况下 两种中间件都在middlewares.py一个文件中,爬虫中间件使用方法和下载中间件相同,且功能重复,通常使用下载中间件

中间件分类

下载中间件(Download Middleware):

下载中间件用于处理Scrapy发送给下载器的请求和下载器返回给Scrapy的响应。下载中间件可以通过修改请求和响应,实现诸如代理、用户代理、重试、超时等功能。

Spider中间件(Spider Middleware):

Spider中间件用于处理Scrapy接收到的Spider产生的请求和Spider处理响应时产生的Item和爬虫数据。Spider中间件可以通过修改请求和响应,实现诸如添加头部、身份验证、反爬虫等功能。

自定义中间件后,需要在settings.py文件中进行配置

python
复制代码
# 下载中间件
DOWNLOADER_MIDDLEWARES = {
    'myproject.middlewares.MyDownloaderMiddleware': 543,
}

# Spider中间件
SPIDER_MIDDLEWARES = {
    'myproject.middlewares.MySpiderMiddleware': 543,
}

注意:如果多个中间件定义了相同的方法,则后面的中间件将覆盖前面的中间件。

常见中间件

Scrapy默认提供如下的下载中间件:

python
复制代码
scrapy.contrib.downloadermiddleware.useragent.UserAgentMiddleware: 设置请求头 User-Agent 信息

scrapy.contrib.downloadermiddleware.retry.RetryMiddleware: 对下载请求失败后进行重试

scrapy.contrib.downloadermiddleware.redirect.RedirectMiddleware: 处理响应重定向

scrapy.contrib.downloadermiddleware.httpproxy.HttpProxyMiddleware: 设置代理

scrapy.contrib.downloadermiddleware.cookies.CookiesMiddleware: 处理请求和响应携带的 Cookies

scrapy.contrib.downloadermiddleware.downloadtimeout.DownloadTimeoutMiddleware: 设置下载超时

scrapy.contrib.downloadermiddleware.httpcache.HttpCacheMiddleware: 处理响应缓存

Scrapy默认提供如下Spider中间件:

python
复制代码
scrapy.spidermiddlewares.httperror.HttpErrorMiddleware: 处理请求异常(HTTP 异常状态码)的中间件

scrapy.spidermiddlewares.offsite.OffsiteMiddleware: 过滤掉不在 allowed_domains 中的请求

scrapy.spidermiddlewares.referer.RefererMiddleware: 自动设置请求的 Referer 头信息

scrapy.spidermiddlewares.urllength.UrlLengthMiddleware: 过滤掉 URL 过长的请求

scrapy.spidermiddlewares.depth.DepthMiddleware: 限制爬取深度

scrapy.spidermiddlewares.httpauth.HttpAuthMiddleware: 处理 HTTP 认证

scrapy.spidermiddlewares.downloadtimeout.DownloadTimeoutMiddleware: 处理下载超时

scrapy.spidermiddlewares.defaultheaders.DefaultHeadersMiddleware: 添加默认请求头

scrapy.spidermiddlewares.httpcache.HttpCacheMiddleware: 处理响应缓存

核心方法

下载中间件

以下是 Scrapy下载中间件中的一些核心方法:

1.process_request(self, request, spider):

处理请求前的方法,接收两个参数。当每个request通过下载中间件时,该方法被调用。可以通过修改请求头、代理、Cookie等来处理请求或将其过滤掉,或者返回 None 以允许其他中间件或下载器处理请求。

python
复制代码
request: 请求对象
spider: 请求来自的爬虫

return None         继续处理这个请求
return Response     不再请求,直接把响应提交给引擎 -> 爬虫 
return Request      把request对象返回给引擎,通过引擎交给调度器
raise IgnoreRequest 触发 process_exception 回调函数

2.process_response(self, request, response, spider):

处理响应后的方法,接收三个参数。当下载器完成http请求,传递响应给引擎的时候调用。可以对响应做出修改或解析,也可以通过重新传递请求来重试。

python
复制代码
request: 请求对象
response: 请求响应
spider: 请求来自的爬虫

return Response 通过引擎交给爬虫处理或交给权重更低的其他下载中间件的process_response方法
return Request 通过引擎交给调取器继续请求
raise IgnoreRequest 把这请求忽略

3.def process_exception(self, request, exception, spider):

处理下载时出现异常的方法,接收三个参数。当下载中间件异常异常时回调

python
复制代码
request: 请求对象
exception: 异常
spider: 请求来自的爬虫

return None 继续处理异常,向下一个中间件传递异常

return a Response   停止异常链,把响应返回给引擎
return a Request    停止异常链,把请求返回给引擎

4.process_item(item, spider):

在下载器将处理过的响应作为 Item 对象返回给 Spider 之后调用。它接收一个 Item 对象 item,同时还有一个 Spider 对象 spider。可以进一步修改 Item 对象,如添加自定义数据。

这些方法需要根据具体的需求进行实现,可以继承 Scrapy 提供的下载中间件基类 scrapy.contrib.downloadermiddleware.DownloaderMiddleware,然后重写需要的方法来实现自己的功能。

爬虫中间件

在 Scrapy 中,爬虫中间件是用来处理 Scrapy 引擎和爬虫之间交互的中间件。下面是 Scrapy 爬虫中间件的核心方法:

1.process_spider_input(response, spider):

在响应返回给 Spider 之前调用的。它接收一个响应对象 response 和一个 Spider 对象 spider 作为参数。可以在此处理或修改响应对象,如解析响应内容或检查响应状态码。

2.process_spider_output(response, result, spider):

在 Spider 处理响应之后调用的。它接收一个响应对象 response、从 Spider 回传的结果 result、以及一个 Spider 对象 spider 作为参数。可以在此处理或修改 Spider回传的结果(通常是 Item 对象或 Request 对象)。

3.process_spider_exception(response, exception, spider):

Spider 运行时发生异常时调用。它接收三个参数:一个响应对象 response、一个异常对象 exception,以及一个 Spider 对象 spider。可以处理异常,例如打印错误日志或重试请求。

4.process_start_requests(start_requests, spider):

在Spider 启动时调用,接收两个参数:一个 StartRequests 对象 start_requests 和一个 Spider 对象 spider。 StartRequests 对象封装了通过 Spider 方法 start_requests 返回的所有 Request 对象。可以进一步地修改或处理这些请求对象,例如添加请求头或修改请求参数。

自定义实现中间件

实现一个中间件,只需要在middlewares.py文件中创建中间件类,实现所需要拦截的函数

在settings.py中配置开启中间件,在配置中数字越小越优先执行

1.随机UA下载中间件

python
复制代码
import random

def get_ua():
    first_num = random.randint(55, 62)
    third_num = random.randint(0, 3200)
    fourth_num = random.randint(0, 140)
    os_type = [
        '(Windows NT 6.1; WOW64)', '(Windows NT 10.0; WOW64)', '(X11; Linux x86_64)',
        '(Macintosh; Intel Mac OS X 10_12_6)'
    ]
    chrome_version = 'Chrome/{}.0.{}.{}'.format(first_num, third_num, fourth_num)

    ua = ' '.join(['Mozilla/5.0', random.choice(os_type), 'AppleWebKit/537.36',
                   '(KHTML, like Gecko)', chrome_version, 'Safari/537.36']
                  )
    return ua
    


class RandomUserAgentDownloadMiddleware(object):
    def process_request(self, request, spider):
        request.headers["User-Agent"] = get_ua()

        return None

class CheckUA:
    def process_response(self,request,response,spider):
        print(request.headers['User-Agent'])
        return response

在settings中设置开启自定义的下载中间件

python
复制代码
DOWNLOADER_MIDDLEWARES = {
	'myproject.middlewares.RandomUserAgentDownloadMiddleware': 500,
	'myproject.middlewares.CheckUA': 600,# 先执行500权重的中间件,再执行600的中间件
}

也可以在settings中添加UA的列表,在中间件中导入

python
复制代码
USER_AGENTS_LIST = []
python
复制代码
from projectName.settings import USER_AGENTS_LIST

2.代理中间件

python
复制代码
class RandomProxyDownloadMiddleware(object):
    def process_request(self, request, spider):
    	# 在settings.py中定义proxies
        # request.meta["proxy"] = random.choice(PROXIES)
        
        # 通过请求方式获取代理
        proxy = requests.get('http://127.0.0.1:8888/proxies/random').text
        request.meta["proxy"] = proxy
        return None

在下载中间件的process_response()方法中处理代理ip的使用情况,如果该代理ip不能使用可以替换其他代理ip

python
复制代码
    def process_response(self, request, response, spider):
        if response.status != '200':
            request.dont_filter = True  # 重新发送的请求对象能够再次进入队列
            return request

3.selenium 中间件

python
复制代码
class SeleniumDownloadMiddleware(object):
    def process_request(self, request, spider):

        options = webdriver.ChromeOptions()
        options.add_argument('--headless')  # 开启无界面模式
        options.add_argument('--disable-gpu')  # 禁用gpu,解决一些莫名的问题

        browser = webdriver.Chrome('./chromedriver',options=options)
        browser.get(request.url)

        response = HtmlResponse(
            url=browser.current_url,
            body=browser.page_source,
            encoding='utf-8'
        )

        browser.quit()

        return response

这里给大家分享一份Python全套学习资料,包括学习路线、软件、源码、视频、面试题等等,都是我自己学习时整理的,希望可以对正在学习或者想要学习Python的朋友有帮助!

CSDN大礼包:全网最全《全套Python学习资料》免费分享🎁

😝有需要的小伙伴,可以点击下方链接免费领取或者V扫描下方二维码免费领取🆓

👉CSDN大礼包🎁:全网最全《Python学习资料》免费分享(安全链接,放心点击)👈

1️⃣零基础入门

① 学习路线

对于从来没有接触过Python的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
在这里插入图片描述

② 路线对应学习视频

还有很多适合0基础入门的学习视频,有了这些视频,轻轻松松上手Python~在这里插入图片描述

③练习题

每节视频课后,都有对应的练习题哦,可以检验学习成果哈哈!
在这里插入图片描述
因篇幅有限,仅展示部分资料

2️⃣国内外Python书籍、文档

① 文档和书籍资料

在这里插入图片描述

3️⃣Python工具包+项目源码合集

①Python工具包

学习Python常用的开发软件都在这里了!每个都有详细的安装教程,保证你可以安装成功哦!
在这里插入图片描述

②Python实战案例

光学理论是没用的,要学会跟着一起敲代码,动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。100+实战案例源码等你来拿!
在这里插入图片描述

③Python小游戏源码

如果觉得上面的实战案例有点枯燥,可以试试自己用Python编写小游戏,让你的学习过程中增添一点趣味!
在这里插入图片描述

4️⃣Python面试题

我们学会了Python之后,有了技能就可以出去找工作啦!下面这些面试题是都来自阿里、腾讯、字节等一线互联网大厂,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
在这里插入图片描述
在这里插入图片描述

5️⃣Python兼职渠道

而且学会Python以后,还可以在各大兼职平台接单赚钱,各种兼职渠道+兼职注意事项+如何和客户沟通,我都整理成文档了。
在这里插入图片描述
在这里插入图片描述
上述所有资料 ⚡️ ,朋友们如果有需要 📦《全套Python学习资料》的,可以扫描下方二维码免费领取 🆓
😝有需要的小伙伴,可以点击下方链接免费领取或者V扫描下方二维码免费领取🆓

👉CSDN大礼包🎁:全网最全《Python学习资料》免费分享(安全链接,放心点击)👈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值