首页 > 其他分享 >Scrapy | 通过爬取豆瓣Top250电影信息来学习在中间件中应用随机请求头和代理ip

Scrapy | 通过爬取豆瓣Top250电影信息来学习在中间件中应用随机请求头和代理ip

时间:2024-10-22 18:49:47浏览次数:8  
标签:5.0 中间件 request scrapy 爬取 Scrapy div response

中间件的使用

  • 目标

1.应用scrapy中使用间件使用随机UA的方法
2.应用scrapy中使用代理ip的的方法
3.应用scrapy.与selenium配合使用

1.scrapyl中间件的分类和作用

1.1 scrapy中间件的分类

根据scrapyi运行流程中所在位置不同分为:

1.下载中间件
2.爬虫中间件

在这里插入图片描述

1.2 scrapy中间的作用:预处理request和response对象

1.对header以及cookie进行更换和处理
2.使用代理ip等
3.对请求进行定制化操作,

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

2.下载中间件的使用方法:

接下来我们对腾讯招聘爬虫进行修改完善,通过下载中间件来学习如何使用中间件编写一个 Downloader Middlewares和我们编写一个pipeline一样,定义一个类,然后在setting中开启

1.在middlerware.py中定义中间件类
2.在中间件类中,重写处理清求或者响应的方法
3.在settings文件中开启中间件的使用

Downloader Middlewares默认的方法:


process_request(self,request,spider):
	1.当每个requesti通过下载中间件时,该方法被调用。
	2.返回None值:没有return也是返回None,该request对象传递给下载器,或通过引擎传递给其他权重低的process,_request方法
	3.返回Response对象:不再请求,把response返回给引繁
	4.返回Request对象:把request对象通过引擎交给调度器,此时将不通过其他权重低的process_request方法


protess_response(self,request,response,spider):
	1.当下载器完成http请求,传递响应给引擎的时候调用
	2.返回Resposne:通过引擎交给爬虫处理或交给权重更低的其他下载中间件的process_response方法
	3.返回Request对象:通过引擎交给调取器继续请求,此时将不通过其他权重低的process_request方法

在settings.py中配置开启中间件,权重值越小越优先执行

3.定义实现随机User-Agent的下载中间件

3.1 实战:爬取豆瓣Top250电影信息

  • 网页分析
    在这里插入图片描述
    在这里插入图片描述
  • 代码

记得在settings.py设置User-Agent和ROBOTSTXT_OBEY,否则会报403错误

# items.py
# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html

import scrapy


class DoubanItem(scrapy.Item):
    # define the fields for your item here like:
    name = scrapy.Field()
    info = scrapy.Field()
    score = scrapy.Field()
    desc = scrapy.Field()
    pass

import scrapy
from douban.items import DoubanItem

class MovieSpider(scrapy.Spider):
    name = 'movie'
    allowed_domains = ['douban.com']
    start_urls = ['https://movie.douban.com/top250']

    def parse(self, response):
        node_list = response.xpath('//div[@class="info"]')
        # print(len(node_list))

        for node in node_list:
            item = DoubanItem()
            item['name'] = node.xpath('./div[1]/a/span[1]/text()').get()
            item['info'] = node.xpath('./div[@class="bd"]/p[1]/text()').extract_first().replace('\n','').replace(' ','')
            item['score'] = node.xpath('./div[@class="bd"]/div[@class="star"]/span[2]/text()').extract_first()
            item['desc'] = node.xpath('./div[2]/p[2]/span/text()').extract_first()

            yield item


        nexturl = response.xpath('//span[@class="next"]/a/@href').get()   #没有 a  则到最后一页提取的是Nnoe

        if nexturl != None:
            url = response.urljoin(nexturl)
            yield scrapy.Request(
                url=url
            )



  • 结果
    在这里插入图片描述

3.2 中间件使用实现随机User-Agent

在这里插入图片描述
如上,请求头是写死在settings.py中的,请求发送的多了 也是会出问题的

  • seeings.py 设置 USER_AGENT_List 参数
USER_AGENT_List=[
    "Opera/12.0(Windows NT 5.2;U;en)Presto/22.9.168 Version/12.00",
    "Opera/12.0(Windows NT 5.1;U;en)Presto/22.9.168 Version/12.00",
    "Mozilla/5.0 (Windows NT 5.1) Gecko/20100101 Firefox/14.0 Opera/12.0",
    "Opera/9.80 (Windows NT 6.1; WOW64; U; pt) Presto/2.10.229 Version/11.62",
    "Opera/9.80 (Windows NT 6.0; U; pl) Presto/2.10.229 Version/11.62",
    "Mozilla/5.0 (Microsoft Windows NT 6.2.9200.0); rv:22.0) Gecko/20130405 Firefox/22.0",
    "Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:16.0.1) Gecko/20121011 Firefox/21.0.1",
    "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:16.0.1) Gecko/20121011 Firefox/21.0.1",
    "Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:21.0.0) Gecko/20121011 Firefox/21.0.0",
    "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:21.0) Gecko/20130331 Firefox/21.0",
    "Mozilla/5.0 (Windows; U; MSIE 9.0; WIndows NT 9.0; en-US))",
    "Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)",
    "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 7.1; Trident/5.0)",
    "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; Media Center PC 6.0; InfoPath.3; MS-RTC LM 8; Zune 4.7)",
    "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; Media Center PC 6.0; InfoPath.3; MS-RTC LM 8; Zune 4.7",
    "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Zune 4.0; InfoPath.3; MS-RTC LM 8; .NET4.0C; .NET4.0E)",
    "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; chromeframe/12.0.742.112)",
    "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
    "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
    "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 2.0.50727; SLCC2; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Zune 4.0; Tablet PC 2.0; InfoPath.3; .NET4.0C; .NET4.0E)",
]
  • middlewares.py设置
import random
from douban.settings import  USER_AGENT_List
# useful for handling different item types with a single interface
from itemadapter import is_item, ItemAdapter

class RandomUserAgent(object):
	#处理请求头  设置随机请求头 
    def process_request(self,request,spider):
        # print(request.headers['User-Agent'])
        ua = random.choice(USER_AGENT_List)
        request.headers['User-Agent']=ua

在这里插入图片描述

  • settings.py 开启中间件
DOWNLOADER_MIDDLEWARES = {
   # 'douban.middlewares.DoubanDownloaderMiddleware': 543,
    'douban.middlewares.RandomUserAgent': 543, # RandomUserAgent 中间件名称

}
  • 爬虫.py
    同上,直接执行即可
def parse(self, response):
    print(response.request.headers['User-Agent'])  # 增加一行测试代码

    node_list = response.xpath('//div[@class="info"]')
    # print(len(node_list))

    for node in node_list:
        item = DoubanItem()
        item['name'] = node.xpath('./div[1]/a/span[1]/text()').get()
        item['info'] = node.xpath('./div[@class="bd"]/p[1]/text()').extract_first().replace('\n','').replace(' ','')
        item['score'] = node.xpath('./div[@class="bd"]/div[@class="star"]/span[2]/text()').extract_first()
        item['desc'] = node.xpath('./div[2]/p[2]/span/text()').extract_first()

        yield item
scrpay crawl douban
  • 结果
    在这里插入图片描述
    仔细观察上述结果有10个请求头,因为Top250的豆瓣网页每页25个电影数据 一共10页数据 因此每个页面使用一个请求头
    在这里插入图片描述

4. 代理ip的使用

4.1思路分析

1.代理添加的位置:request…meta中增加proxy字段
2.获取一个代理ip,赋值给request.meta['proxy']

  • 代理池中随机选择代理p
  • 代理ip的webapi发送请求获取一个代理ip

4.2 代码实现

  • settings.py
PROXY_LIST = [
    {"ip_port":"123.207.53.84:16816","user_passwd":"morganne_mode_gigqc229x0"}, # 付费的稳定
    {"ip_port": "202.101.213.63:15007"} ,# 免费
    {"ip_port": "218.87.205.96:23763"},# 免费
]
  • middlewares.py
class RandomProxy(object):
    # 免费代理
    def process_request(self,request,spider):
        proxy = random.choice(PROXY_LIST)
        request.headers['proxy'] = proxy
        print(proxy)
        
		# 付费的有账号密码
        if 'user_passwd' in proxy:
            # 对帐号密码进行编码:
            base_up = base64.b64encode(proxy['user_passwd'].encode())
            # encode() 方法用于将字符串转换为字节串(bytes)
            # base64.b64encode() 需要一个字节串作为输

            # 设置认证
            request.headers['Proxy-Authorization'] = 'Basic '+ base_up.decode()
            # 将这个字节串解码为一个普通字符串(str),使其可以作为HTTP头部值或其他需要字符串格式的场景使用
            # Basic :后面有一个空格  这个一定要有   用来切割  一个是认证方式 一个是账号密码

            # 设置代理
            request.meta['proxy'] = proxy['ip_port']
        else:
            # 设置代理
            request.meta['proxy'] = proxy['ip_port']
代码:base64.b64encode(auth.encode()).decode()

在Python中,base64.b64encode() 函数用于将字节串(bytes)编码为Base64格式的字符串。auth.encode() 是将字符串(str)转换为字节串(bytes),因为 base64.b64encode() 需要一个字节串作为输入。

以下是详细步骤和代码解释:

  1. 字符串转字节串

    • auth.encode():将字符串 auth 转换为字节串。在Python 3中,字符串是以Unicode形式存储的,而 encode() 方法将Unicode字符串转换为字节串。默认情况下,它使用UTF-8编码,但你也可以指定其他编码方式。
  2. 字节串编码为Base64

    • base64.b64encode():这个函数接受一个字节串作为输入,并返回一个新的字节串,该字节串是原始字节串的Base64编码。
  3. 字节串解码为字符串

    • .decode():Base64编码后的结果是一个字节串,.decode() 方法将这个字节串解码为一个普通字符串(str),使其可以作为HTTP头部值或其他需要字符串格式的场景使用。

我们使用 requests 库发送一个带有代理认证的HTTP GET请求。认证信息被编码为Base64,并设置在请求头中。这样,请求就可以通过需要认证的代理服务器了。

5. 在中间件中使用selenium - 未实现 了解即可

空气质量历史数据查询为例

获取爬取网页的url(包括一级网址、二级网址) >>> 依据二级网址获得城市指数 >>> 依据一级网址热门城市的城市名称、城市链接(根据城市链接【二级网址】获得城市的指数数据

5.1分析网页数据格式

  • 首页
    在这里插入图片描述

  • 具体城市页
    在这里插入图片描述
    在这里插入图片描述

  • 具体城市具体月份
    在这里插入图片描述
    在这里插入图片描述

因为数据页不让调试 因此 此部分代码用做学习 并没有运行结果

import scrapy

from AQI.items import AqiItem


class AirdataSpider(scrapy.Spider):
    name = 'airdata'
    allowed_domains = ['aqistudy.cn']
    start_urls = ['https://www.aqistudy.cn/historydata/']

	#  这个还是可以运行的
    def parse(self, response):
        # 获取城市名列表      内容很多  只用一个 阿坝州
        city_name_list = response.xpath('/html/body/div[3]/div/div[1]/div[2]/div[2]/ul/div[2]/li/a/text()').getall()[0]
        print('city_name_list : %s'%city_name_list )
        # 获取跳转具体城市url列表:   内容很多  只用一个  阿坝州
        link_list = response.xpath('/html/body/div[3]/div/div[1]/div[2]/div[2]/ul/div[2]/li/a/@href').extract()[0:1]
        print('link_list : %s'% link_list )

        # 遍历列表
        for name, link in zip(city_name_list, link_list):
            # 给城市名赋值
            item = AqiItem()
            item['city_name'] = name
            # 完整的link
            # link = self.base_url + str(link)
            link = response.urljoin(link)
            print('link : %s' % link)
            # 发起请求,获取月度信息
            yield scrapy.Request(url=link, meta={'api_item': item}, callback=self.parse_month)

	def parse_month(self, response):
		pass

    def parse_day(self, response):
		pass

在这里插入图片描述

5.2 selenium中间件的使用 ⭐

scrapy本身就相当于request,它不能处理渲染之后的数据,因此使用selenium来处理渲染后的数据 ,具体城市具体月份对应的网页数据是需要渲染的


from selenium import webdriver
import scrapy
import time


# 通过中间件自定义 webdriver的下载器
class ChromeMiddlewares(object):
    def process_request(self, request, spider):
        # 网址
        url = request.url

        # 判断,如果首页,不需要自定义
        if url != 'https://www.aqistudy.cn/historydata/':
            # 发送请求
            driver = webdriver.Chrome()
            driver.get(url)

            # 注意添加延迟  由于是动态加载的
            time.sleep(2)

            # 获取数据
            data = driver.page_source

            # 关闭浏览器
            driver.close()

            # 构建自己的response对象,直接返回
            return scrapy.http.HtmlResponse(url=url, body=data, encoding='utf-8', request=request)

在这里插入图片描述

  • 开启中间件
    在这里插入图片描述

标签:5.0,中间件,request,scrapy,爬取,Scrapy,div,response
From: https://blog.csdn.net/HG0724/article/details/143091331

相关文章

  • 使用Python爬取某车网参数详情并解析数据
    前言在本文中,我们将介绍如何使用Python来获取某汽车网站的参数详情,并将有用的数据提取出来保存到本地。我们将使用requests库来发送网络请求,同时利用随机User-Agent和代理IP来模拟真实用户的访问行为,以避免被服务器封禁。目标网站1.准备工作首先,我们需要安装一些必要......
  • django中间件
    什么是中间件是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能MiddlewareisaframeworkofhooksintoDjango’srequest/responseprocessing.It’salight,lo......
  • |动漫爬取|001_djangodjango基于Spark的国漫推荐系统的设计与实现2024_tpd6q1o4
    目录系统展示开发背景代码实现项目案例 获取源码博主介绍:CodeMentor毕业设计领航者、全网关注者30W+群落,InfoQ特邀专栏作家、技术博客领航者、InfoQ新星培育计划导师、Web开发领域杰出贡献者,博客领航之星、开发者头条/腾讯云/AWS/Wired等平台优选内容创作者、深耕Web......
  • 爬虫爬取豆瓣top250电影信息
     使用正则解析,获得名字,影片信息,打分,评价人数,影评等数据。存储到csv文件中,少部分数据爬取不到还存在优化空间。importrequestsimportreimportcsv#拿到豆瓣top250网站源码headers={"User-Agent":"Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36......
  • 【python爬虫案例】利用python爬取豆瓣音乐评分TOP250的排行数据!
    一、爬取案例-豆瓣音乐TOP250之前给大家分享了2个豆瓣的python爬虫案例:【python爬虫案例】利用python爬虫爬取豆瓣电影评分TOP250排行数据!【python爬虫案例】利用python爬虫爬取豆瓣读书评分TOP250的排行数据! 今天再给大家分享一下:豆瓣音乐排行榜TOP250的python爬虫案例!爬......
  • 【python爬虫案例】利用python爬取B站TOP100热门排行榜附源码
    目录一、爬取目标-B站排行榜二、B站排行榜网站分析三、B站排行榜爬虫代码详解四、B站排行榜结果五、python爬虫源代码获取一、爬取目标-B站排行榜大家好,我是老王!今天给大家分享一期python爬虫案例,这次爬取的对象是:B站热门排行榜数据爬取的目标网址是:https://www.bil......
  • Python爬虫快速入门(Requests+BeautifulSoup+Scrapy)
    目录1.为什么需要爬虫2.爬虫的方法2.1Requests2.2BeautifulSoup2.3Scrapy3.爬虫的注意事项1.为什么需要爬虫    爬虫是重要的数据获取方式,理论上任何网上公开可视的数据都是可以获取到的。在学术研究等场合中除了使用直接的数据集以及各种搜索引擎提......
  • 使用Python爬取免费代理并测试其有效性
    前言在本篇文章中,我们将使用Python编写一个脚本来爬取免费的代理IP地址,并对其进行有效性测试。我们将会用到playwright、aiohttp、pandas等库来完成这个任务。最终我们会得到一个包含有效代理IP地址的列表,并将其保存到本地文件中。1.环境准备首先,你需要确保你的Python环......
  • Express的使用笔记3 中间件
    日志中间件//挂载会每个接口都执行这段代码app.use((req,res,next)=>{console.log(req.method,req.url,Date.now())next()//下一个中间件})2.中间件的顺序很重要如果有一个普通接口写在上面代码之前,那么就不会进入上面的函数中但是如果在接口中第二个回调......
  • scrapy框架学习笔记
    scrapy运行机制详见Architectureoverview安装直接pipinstallscrapy即可使用命令行scrapystartprojectname命令创建一个新的Scrapy项目scrapycrawlSpiderName命令运行爬虫scrapyrunspiderSpiderName命令运行脚本。更多命令直接查Commandlinetool概述编写S......