反爬
1.反爬虫的原因
- 降低服务器负载
- 爬虫占用服务器资源,影响正常用户
- 假设服务器同时可以接受10个请求,一个爬虫就可以利用多线程全部占用
- 维护企业的竞争力
2.常见反爬的三个方向
- 判断用户身份
- User-Agent ·
- Cookies ·
- Refer ·
- 验证码 ·
- 分析用户行为
- 通过并发识别爬虫 ·
- 在线活动时间 ·
- 页面添加一些正常浏览器浏览访问不到的资源
- 动态加载数据
- js
- ajax
scrapy反爬应对与下载器中间件
Scrapy常见反反爬措施
- 1)模拟用户头 设置位置:
- ①settings文件
- ②创建请求时
- ③下载器中间件
- 2)请求延迟
- settings文件中 DOWNLOAD_DELAY = n 测试目标站点阈值后设置
- 3)Cookies检测
- settings文件中 COOKIES_ENABLED = False
- 4)使用ip代理池
- 中间件里设置
- 除了官方的crawlera代理其余的都需要在下载器中间件中设置ip代理
通常防止爬虫被反主要有以下几个策略:
- 动态设置User-Agent(随机切换User-Agent,模拟不同用户的浏览器信息)
- 禁用Cookies(也就是不启用cookies middleware,不向Server发送cookies,有些网站通过cookie的使用发现爬虫行为)
- 可以通过
COOKIES_ENABLED
控制 CookiesMiddleware 开启或关闭
- 设置延迟下载(防止访问过于频繁,设置为 2秒 或更高)
- Google Cache 和 Baidu Cache:如果可能的话,使用谷歌/百度等搜索引擎服务器页面缓存获取页面数据。
- 使用IP地址池:VPN和代理IP,现在大部分网站都是根据IP来ban的。
- 使用 Crawlerahttps://scrapinghub.com/crawlera(专用于爬虫的代理组件),正确配置和设置下载中间件后,项目所有的request都是通过crawlera发出。
DOWNLOADER_MIDDLEWARES = {
'scrapy_crawlera.CrawleraMiddleware': 600
}
CRAWLERA_ENABLED = True
CRAWLERA_USER = '注册/购买的UserKey'
CRAWLERA_PASS = '注册/购买的Password'
设置下载中间件(Downloader Middlewares)
激活下载器中间件组件
DOWNLOADER_MIDDLEWARES = {
'mySpider.middlewares.MyDownloaderMiddleware': 543,
}
setting配置
Scrapy设置(settings)提供了定制Scrapy组件的方法。可以控制包括核心(core),插件(extension),pipeline及spider组件。比如 设置Json Pipeliine、LOG_LEVEL等。
参考文档:http://scrapy-chs.readthedocs.io/zh_CN/1.0/topics/settings.html#topics-settings-ref
内置设置参考手册
BOT_NAME
- 默认: 'scrapybot'
- 当您使用 startproject 命令创建项目时其也被自动赋值。
CONCURRENT_ITEMS
- 默认: 100
- Item Processor(即 Item Pipeline) 同时处理(每个response的)item的最大值。
CONCURRENT_REQUESTS
- 默认: 16
- Scrapy downloader 并发请求(concurrent requests)的最大值。
DEFAULT_REQUEST_HEADERS
- 默认: 如下
{
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en',
}
Scrapy HTTP Request使用的默认header。
DEPTH_LIMIT
- 默认: 0
- 爬取网站最大允许的深度(depth)值。如果为0,则没有限制。
DOWNLOAD_DELAY
- 默认: 0
- 下载器在下载同一个网站下一个页面前需要等待的时间。该选项可以用来限制爬取速度, 减轻服务器压力。同时也支持小数:
DOWNLOAD_DELAY = 0.25 # 250 ms of delay
- 默认情况下,Scrapy在两个请求间不等待一个固定的值, 而是使用0.5到1.5之间的一个随机值 * DOWNLOAD_DELAY 的结果作为等待间隔。
DOWNLOAD_TIMEOUT
- 默认: 180
- 下载器超时时间(单位: 秒)。
ITEM_PIPELINES
- 默认: {}
- 保存项目中启用的pipeline及其顺序的字典。该字典默认为空,值(value)任意,不过值(value)习惯设置在0-1000范围内,值越小优先级越高。
ITEM_PIPELINES = {
'mySpider.pipelines.SomethingPipeline': 300,
'mySpider.pipelines.ItcastJsonPipeline': 800,
}
LOG_ENABLED
- 默认: True
- 是否启用logging。 运行时 是否打印log信息
LOG_ENCODING
- 默认: 'utf-8'
- logging使用的编码。显示log日志的编码格式
- LOG_FILE
- 生成log文件
- LOG_FILE = 'mylog.log'
LOG_LEVEL
- 默认: 'DEBUG'
- 设置格式为
LOG_LEVEL = "INFO" #
- log的最低级别。可选的级别有:
- CRITICAL - 严重错误(critical)
- ERROR - 一般错误(regular errors)
- WARNING - 警告信息(warning messages) 一般除警告错误不会打印
- INFO - 一般信息(informational messages) 打印爬虫返回的数据 及引擎返回的数据
- DEBUG - 调试信息(debugging messages)
- LOG_FILE
- log文件路径
USER_AGENT
- 默认:
"Scrapy/VERSION (+http://scrapy.org)"
- 爬取的默认User-Agent,除非被覆盖。
PROXIES
: 代理设置
- 示例:
PROXIES = [
{'ip_port': '111.11.228.75:80', 'password': ''},
{'ip_port': '120.198.243.22:80', 'password': ''},
{'ip_port': '111.8.60.9:8123', 'password': ''},
{'ip_port': '101.71.27.120:80', 'password': ''},
{'ip_port': '122.96.59.104:80', 'password': ''},
{'ip_port': '122.224.249.122:8088', 'password':''},
]
COOKIES_ENABLED = False
- 禁用Cookies
#CONCURRENT_REQUESTS_PER_DOMAIN = 16 # 对同一个域名同时有多少个请求
#CONCURRENT_REQUESTS_PER_IP = 16 # 每一ip的并发数量
在配置文件中设置路径
IMAGES_STORE = '/home/python/Desktop/Spider/day06-框架豆瓣电影_斗鱼妹子/Douban/Douban'
import os
import scrapy
# 三种导入setting文件的方法
from scrapy.utils.project import get_project_settings
from Itcast.settings import IMAGES_STORE
from scrapy.conf import settings
# 导入该类
from scrapy.pipelines.images import ImagesPipeline
class xxxxPipeline(object):
def process_item(self, item, spider):
return item
class ImagePipeline(ImagesPipeline):
IMAGES_STORE = get_project_settings().get('IMAGES_STORE')
def get_media_requests(self, item, info):
# 获取照片并保存到setting指定的路径
# print(self.IMAGES_STORE)
yield scrapy.Request(url=item['img_url'])
# print('-'*88)
def item_completed(self, results, item, info):
# results会把保存的信息返回 可以对下载的文件名进行操作 以下为修改照片名字的案例
img_path = [data["path"] for ok, data in results]
# 旧
old_path = self.IMAGES_STORE + os.sep + img_path[0]
# 新
new_path = self.IMAGES_STORE + os.sep + img_path[0].split('/')[0] + os.sep + item["name"] +'.jpg'
# 换路径
os.rename(old_path, new_path)
return item
图片下载器 Code