10 UA池和代理池
下载中间件简介
在Scrapy中,引擎和下载器之间有一个组件,叫下载中间件(Downloader Middlewares)。因它是介于Scrapy的request/response处理的钩子,所以有2方面作用:
(1)引擎将请求传递给下载器过程中,下载中间件可以对Requests进行一系列处理。比如设置请求的 User-Agent,设置代理ip等
(2)在下载器完成将Response传递给引擎中,下载中间件可以对Responses进行一系列处理。比如进行gzip解压等。

下载中间件有以下几个函数被管理
- process_request request通过下载中间件时,该方法被调用
- process_response 下载结果经过中间件时被此方法处理
- process_exception 下载过程中出现异常时被调用
编写中间件时,需要思考要实现的功能最适合在那个过程处理,就编写哪个方法。中间件可以用来处理请求,处理结果或者结合信号协调一些方法的使用等,也可以在原有的爬虫上添加适应项目的其他功能,这一点在扩展中编写也可以达到目的,实际上扩展更加去耦合化,推荐使用扩展。爬虫中,主要使用下载中间件处理请求,一般会对请求设置随机的User-Agent ,设置随机的代理ip。目的在于防止爬取网站的反爬虫策略。
一、UA池:User-Agent池
- 作用:尽可能多的将scrapy工程中的请求伪装成不同类型的浏览器身份。
- 操作流程:
1.在下载中间件中拦截请求
2.将拦截到的请求的请求头信息中的UA进行篡改伪装
3.在配置文件中开启下载中间件
Middleware.py中部分代码展示:
from scrapy.contrib.downloadermiddleware.useragent import UserAgentMiddleware #导包
import random #UA池代码的编写(单独给UA池封装成一个类)
class RandomUserAgent(UserAgentMiddleware): def process_request(self, request, spider):
ua = random.choice(user_agent_list)
request.headers.setdefault('User-Agent',ua) # 当前拦截到请求的ua的写入操作 user_agent_list = [
"(KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 "
"(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 "
]
二、代理池
- 作用:尽可能多的将scrapy工程中的请求的IP设置成不同的。
- 操作流程:
1.在下载中间件中拦截请求
2.将拦截到的请求的IP修改成某一代理IP
3.在配置文件中开启下载中间件
Middleware代码展示:批量对拦截到的请求进行ip更换, 单独封装下载中间件类
class Proxy(object):
def process_request(self, request, spider):
# 对拦截到请求的url进行判断(协议头到底是http还是https), request.url返回值:http://www.xxx.com
h = request.url.split(':')[0] #请求的协议头
if h == 'https':
ip = random.choice(PROXY_https)
request.meta['proxy'] = 'https://'+ip
else:
ip = random.choice(PROXY_http)
request.meta['proxy'] = 'http://' + ip
#可被选用的代理IP
PROXY_http = [
'153.180.102.104:80',
'195.208.131.189:56055',
]
PROXY_https = [
'120.83.49.90:9000',
'95.189.112.214:35508',
]
代理ip一般都是在发送请求不成功的时候进行的,所以,我们以后可以将代理ip写到process_exception中。
三、UA池和代理池在中间件中的使用示例
以麦田房产为例,将代码展示在下方,详细展示了如何在Scrapy框架中使用UA池和代理池。

爬虫文件:maitian.py
import scrapy
from houseinfo.items import HouseinfoItem # 将item导入 class MaitianSpider(scrapy.Spider):
name = 'maitian'
# start_urls = ['http://bj.maitian.cn/zfall/PG{}'.format(page for page in range(1,101))]
start_urls = ['http://bj.maitian.cn/zfall/PG100'] #解析函数
def parse(self, response): li_list = response.xpath('//div[@class="list_wrap"]/ul/li') for li in li_list:
item = HouseinfoItem(
title = li.xpath('./div[2]/h1/a/text()').extract_first().strip(),
price = li.xpath('./div[2]/div/ol/strong/span/text()').extract_first().strip(),
square = li.xpath('./div[2]/p[1]/span[1]/text()').extract_first().replace('㎡',''),
area = li.xpath('./div[2]/p[2]/span/text()[2]').extract_first().strip().split('\xa0')[0],
adress = li.xpath('./div[2]/p[2]/span/text()[2]').extract_first().strip().split('\xa0')[2]
) yield item # 提交给管道,然后管道定义存储方式
items文件:items.py
import scrapy class HouseinfoItem(scrapy.Item):
title = scrapy.Field() #存储标题,里面可以存储任意类型的数据
price = scrapy.Field()
square = scrapy.Field()
area = scrapy.Field()
adress = scrapy.Field()
管道文件:pipelines.py
class HouseinfoPipeline(object):
def __init__(self):
self.file = None #开始爬虫时,执行一次
def open_spider(self,spider):
self.file = open('maitian.csv','a',encoding='utf-8') # 选用了追加模式
self.file.write(",".join(["标题","月租金","面积","区域","地址","\n"]))
print("开始爬虫") # 因为该方法会被执行调用多次,所以文件的开启和关闭操作写在了另外两个只会各自执行一次的方法中。
def process_item(self, item, spider):
content = [item["title"], item["price"], item["square"], item["area"], item["adress"], "\n"]
self.file.write(",".join(content))
return item # 结束爬虫时,执行一次
def close_spider(self,spider):
self.file.close()
print("结束爬虫")
中间件文件Middlewares.py
from scrapy import signals
class HouseinfoDownloaderMiddleware(object):
#UA池
user_agent_list = [
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 "
"(KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
"Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 "
"(KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 "
"(KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 "
"(KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6",
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 "
"(KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 "
"(KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5",
"Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 "
"(KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 "
"(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 "
"(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 "
"(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 "
"(KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 "
"(KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 "
"(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 "
"(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 "
"(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 "
"(KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 "
"(KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24",
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 "
"(KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"
]
PROXY_http = [
'153.180.102.104:80',
'195.208.131.189:56055',
]
PROXY_https = [
'120.83.49.90:9000',
'95.189.112.214:35508',
]
def process_request(self, request, spider):
#使用UA池设置请求的UA
request.headers['User-Agent'] = random.choice(self.user_agent_list)
return None
def process_response(self, request, response, spider):
return response
#拦截发生异常的请求对象
def process_exception(self, request, exception, spider):
if request.url.split(':')[0] == 'http':
request.meta['proxy'] = 'http://'+random.choice(self.PROXY_http)
else:
request.meta['proxy'] = 'https://' + random.choice(self.PROXY_https)
配置文件:settings.py
# -*- coding: utf-8 -*-
BOT_NAME = 'houseinfo' SPIDER_MODULES = ['houseinfo.spiders']
NEWSPIDER_MODULE = 'houseinfo.spiders' # Obey robots.txt rules
ROBOTSTXT_OBEY = False #开启管道
ITEM_PIPELINES = {
'houseinfo.pipelines.HouseinfoPipeline': 300, #数值300表示为优先级,值越小优先级越高
}
#开启下载中间件
DOWNLOADER_MIDDLEWARES = {
'houseinfo.middlewares.HouseinfoDownloaderMiddleware': 543,
}
直接在spider文件下设置代理,通过传参的方式设置在Request中
import scrapy
from houseinfo.items import HouseinfoItem # 将item导入 class MaitianSpider(scrapy.Spider):
name = 'maitian'
# start_urls = ['http://bj.maitian.cn/zfall/PG{}'.format(page for page in range(1,101))]
start_urls = ['http://bj.maitian.cn/zfall/PG100'] ## 代理设置方式1:直接在代理里设置
def start_requests(self):
urls = [
'http://bj.maitian.cn/zfall/PG100',
# xxx 多个
]
for url in urls:
meta_proxy = ""
if url.startswith("http://"):
meta_proxy = "http://180.96.27.12:88" # http代理
elif url.startswith("https://"):
meta_proxy = "http://109.108.87.136:53281" # https代理 yield scrapy.Request(url=url, callback=self.parse, meta={'proxy': meta_proxy}) #解析函数
def parse(self, response): li_list = response.xpath('//div[@class="list_wrap"]/ul/li') for li in li_list:
item = HouseinfoItem(
title = li.xpath('./div[2]/h1/a/text()').extract_first().strip(),
price = li.xpath('./div[2]/div/ol/strong/span/text()').extract_first().strip(),
square = li.xpath('./div[2]/p[1]/span[1]/text()').extract_first().replace('㎡',''),
area = li.xpath('./div[2]/p[2]/span/text()[2]').extract_first().strip().split('\xa0')[0],
adress = li.xpath('./div[2]/p[2]/span/text()[2]').extract_first().strip().split('\xa0')[2]
) yield item # 提交给管道,然后管道定义存储方式
10 UA池和代理池的更多相关文章
- scrapy下载中间件,UA池和代理池
一.下载中间件 框架图: 下载中间件(Downloader Middlewares) 位于scrapy引擎和下载器之间的一层组件. - 作用: (1)引擎将请求传递给下载器过程中, 下载中间件可以对请 ...
- 爬虫的UA池和代理池
爬虫的UA池和代理池 一.下载中间件 先祭出框架图: 下载中间件(Downloader Middlewares) 位于scrapy引擎和下载器之间的一层组件. - 作用: (1)引擎将请求传递给下 ...
- 12-UA池和代理池
一.UA池和代理池 1.UA池 scrapy的下载中间件: 下载中间件(Downloader Middlewares) 位于s ...
- 14.UA池和代理池
今日概要 scrapy下载中间件 UA池 代理池 今日详情 一.下载中间件 先祭出框架图: 下载中间件(Downloader Middlewares) 位于scrapy引擎和下载器之间的一层组件. - ...
- UA池和代理池
scrapy下载中间件 UA池 代理池 一.下载中间件 先祭出框架图: 下载中间件(Downloader Middlewares) 位于scrapy引擎和下载器之间的一层组件. - 作用: (1)引擎 ...
- UA池和代理池在scrapy中的应用
一.下载中间件 下载中间件(Downloader Middlewares) 位于scrapy引擎和下载器之间的一层组件. - 作用: (1)引擎将请求传递给下载器过程中, 下载中间件可以对请求进行一系 ...
- 爬虫开发13.UA池和代理池在scrapy中的应用
今日概要 scrapy下载中间件 UA池 代理池 今日详情 一.下载中间件 下载中间件(Downloader Middlewares) 位于scrapy引擎和下载器之间的一层组件. - 作用: ( ...
- 14,UA池和代理池
今日概要 scrapy下载中间件 UA池 代理池 一,下载中间件(Downloader Middlewares) 位于scrapy引擎和下载器之间的一层组件. - 作用: (1)引擎将请求传递给下载器 ...
- scrapy的UA池和代理池
一.下载中间件(Downloader Middlewares) 框架图如下 下载中间件(Downloader Middlewares)位于scrapy引擎和下载器之间的一层组件. - 作用: (1)引 ...
随机推荐
- nginx lua集成kafka
NGINX lua集成kafka 第一步:进入opresty目录 [root@node03 openresty]# cd /export/servers/openresty/ [root@node03 ...
- gitee+hexo搭建个人博客
通过gitee和hexo搭建个人博客 首先准备软件: git (提供命令git) git官网 notepad++(方便编辑)notepad++官网 nodejs(hexo依赖)nodejs官网 7z( ...
- HackBar收费版绕过
一段时间没用HackBar,近期做渗透,打开火狐浏览器,按F12键调出HackBar,发现居然需要收费买license才能使用. 经过研究,整理了以下两个绕过HackBar收费版的方法. 第一种:用其 ...
- luogu2279_[HNOI2003]消防局的设立 贪心
传送门 不需要树形dp 关于深度排序 当前节点到最近的消防局(f[u])>2时要建新的与u的上面(v)的上面(w) 同时w的上面和上面的上面也要更新f值 #include <bits/st ...
- 信息收集框架——recon-ng
背景:在渗透测试前期做攻击面发现(信息收集)时候往往需要用到很多工具,最后再将搜集到的信息汇总到一块. 现在有这样一个现成的框架,里面集成了许多信息收集模块.信息存储数据库.以及报告 ...
- mac下使用zerobrane调试cocos2dx的lua
环境:MacOSx 10.9.2, Lua 5.1.4, luaSocket 2.0.2, xcode5.0.2 所需文件 luasocket-2.0.2.zip,ZeroBraneStudioEdu ...
- Netty基础系列(4) --堆外内存与零拷贝详解
前言 到目前为止,我们知道Nio当中有三个最最核心的组件,分别是:Selelctor,Channel,Buffer.在Netty基础系列(3) --彻底理解NIO 这一篇文章中只是进行了大致的介绍. ...
- .Net Core 最优 MD5 打开方式!初学者建议收藏(支持 SHA1,SHA256,.Net Framework)
public static string GetMd5Hash(string input) { using (MD5 md5Hash = MD5.Create()) { // Convert the ...
- JSmooth 将java代码打包成exe
JSmooth 将java代码打包成exe 前言 java代码写了这么多了,但由于jdk的限制,我只能在jdk电脑上运行项目.所以最近在研究打包exe这个问题,今天终于实现了. JSmooth下载 前 ...
- 三步理解--门控循环单元(GRU),TensorFlow实现
1. 什么是GRU 在循环神经⽹络中的梯度计算⽅法中,我们发现,当时间步数较⼤或者时间步较小时,循环神经⽹络的梯度较容易出现衰减或爆炸.虽然裁剪梯度可以应对梯度爆炸,但⽆法解决梯度衰减的问题.通常由于 ...