Scrapy Shell

Scrapy终端是一个交互终端,我们可以在未启动spider的情况下尝试及调试代码

启动Scrapy Shell
scrapy shell "https://hr.tencent.com/position.php?&start=0#a"

Selectors选择器

Scrapy Selectors 内置 XPath 和 CSS Selector 表达式机制
Selector有四个基本的方法,最常用的还是xpath:
xpath(): 传入xpath表达式,返回该表达式所对应的所有节点的selector list列表
extract(): 序列化该节点为Unicode字符串并返回list, extract_first()
css(): 传入CSS表达式,返回该表达式所对应的所有节点的selector list列表,语法同 BeautifulSoup4
re(): 根据传入的正则表达式对数据进行提取,返回Unicode字符串list列表

使用xpath

response.xpath('//title')

Spider类

Spider类定义了如何爬取某个(或某些)网站。包括了爬取的动作(例如:是否跟进链接)以及如何从网页的内容中提取结构化数据(爬取item)。 换句话说,Spider就是你定义爬取的动作及分析某个网页(或者是有些网页)的地方。

scrapy.Spider是最基本的类,所有编写的爬虫必须继承这个类。

主要用到的函数及调用顺序为:
init():
初始化爬虫名字和start_urls列表
start_requests()
调用make_requests_from_url():生成Requests对象交给Scrapy下载并返回response
parse():
解析response,并返回Item或Requests(需指定回调函数)。
Item传给Item pipline持久化,而Requests交由Scrapy下载,并由指定的回调函数处理(默认parse()),一直进行循环,直到处理完所有的数据为止。
Spider类源码参考
#所有爬虫的基类,用户定义的爬虫必须从这个类继承
class Spider(object_ref):

定义spider名字的字符串(string)。

spider的名字定义了Scrapy如何定位(并初始化)spider,所以其必须是唯一的。

name是spider最重要的属性,而且是必须的。

一般做法是以该网站(domain)(加或不加 后缀 )来命名spider。 例如,如果spider爬取 mywebsite.com ,该spider通常会被命名为 mywebsite

name = None

初始化,提取爬虫名字,start_urls

def init(self, name=None, **kwargs):
if name is not None:
self.name = name

如果爬虫没有名字,中断后续操作则报错

elif not getattr(self, 'name', None):
raise ValueError("%s must have a name" % type(self).name)

python 对象或类型通过内置成员dict来存储成员信息

self.dict.update(kwargs)

URL列表。当没有指定的URL时,spider将从该列表中开始进行爬取。 因此,第一个被获取到的页面的URL将是该列表之一。 后续的URL将会从获取到的数据中提取。

if not hasattr(self, 'start_urls'):
self.start_urls = []

打印Scrapy执行后的log信息

def log(self, message, level=log.DEBUG, **kw):
log.msg(message, spider=self, level=level, **kw)

判断对象object的属性是否存在,不存在则断言处理

def set_crawler(self, crawler):
assert not hasattr(self, '_crawler'), "Spider already bounded to %s" % crawler
self._crawler = crawler

@property
def crawler(self):
assert hasattr(self, '_crawler'), "Spider not bounded to any crawler"
return self._crawler

@property
def settings(self):
return self.crawler.settings

该方法将读取start_urls内的地址,并为每一个地址生成一个Request对象,交给Scrapy下载并返回Response

该方法仅调用一次

def start_requests(self):
for url in self.start_urls:
yield self.make_requests_from_url(url)

start_requests()中调用,实际生成Request的函数。

Request对象默认的回调函数为parse(),提交的方式为get

def make_requests_from_url(self, url):
return Request(url, dont_filter=True)

默认的Request对象回调函数,处理返回的response。

生成Item或者Request对象。用户必须实现这个

def parse(self, response):
raise NotImplementedError

@classmethod
def handles_request(cls, request):
return url_is_from_spider(request.url, cls)

def str(self):
return "" % (type(self).name, self.name, id(self))

repr = str
主要属性和方法
  • name

    定义spider名字的字符串。唯一

  • allowed_domains

    包含了spider允许爬取的域名(domain)的列表,可选。

  • start_urls

    初始URL元祖/列表。当没有制定特定的URL时,spider将从该列表中开始进行爬取。

  • start_requests(self)

    该方法必须返回一个可迭代对象(iterable)。该对象包含了spider用于爬取(默认实现是使用 start_urls 的url)的第一个Request。

    当spider启动爬取并且未指定start_urls时,该方法被调用。

  • parse(self, response)

    当请求url返回网页没有指定回调函数时,默认的Request对象回调函数。用来处理网页返回的response,以及生成Item或者Request对象。

  • log(self, message[, level, component])

    使用 scrapy.log.msg() 方法记录日志信息。

CrawlSpider

CrawlSpider是Spider的派生类,Spider类的设计原则是只爬取start_url列表中的网页,而CrawlSpider类定义了一些规则(rule)来提供跟进link的方便的机制,从爬取的网页中获取link并继续爬取的工作更适合。

CrawlSpider类源码参考
class CrawlSpider(Spider):
rules = ()
def init(self, *a, *kw):
super(CrawlSpider, self).init(
a, **kw)
self._compile_rules()

首先调用parse()来处理start_urls中返回的response对象

parse()则将这些response对象传递给了_parse_response()函数处理,并设置回调函数为parse_start_url()

设置了跟进标志位True

parse将返回item和跟进了的Request对象

def parse(self, response):
return self._parse_response(response, self.parse_start_url, cb_kwargs={}, follow=True)

处理start_url中返回的response,需要重写

def parse_start_url(self, response):
return []

def process_results(self, response, results):
return results

从response中抽取符合任一用户定义'规则'的链接,并构造成Resquest对象返回

def _requests_to_follow(self, response):
if not isinstance(response, HtmlResponse):
return
seen = set()

抽取之内的所有链接,只要通过任意一个'规则',即表示合法

for n, rule in enumerate(self._rules):
links = [l for l in rule.link_extractor.extract_links(response) if l not in seen]

使用用户指定的process_links处理每个连接

if links and rule.process_links:
links = rule.process_links(links)

将链接加入seen集合,为每个链接生成Request对象,并设置回调函数为_repsonse_downloaded()

for link in links:
seen.add(link)

构造Request对象,并将Rule规则中定义的回调函数作为这个Request对象的回调函数

r = Request(url=link.url, callback=self._response_downloaded)
r.meta.update(rule=n, link_text=link.text)

对每个Request调用process_request()函数。该函数默认为indentify,即不做任何处理,直接返回该Request.

yield rule.process_request(r)

处理通过rule提取出的连接,并返回item以及request

def _response_downloaded(self, response):
rule = self._rules[response.meta['rule']]
return self._parse_response(response, rule.callback, rule.cb_kwargs, rule.follow)

解析response对象,会用callback解析处理他,并返回request或Item对象

def _parse_response(self, response, callback, cb_kwargs, follow=True):

首先判断是否设置了回调函数。(该回调函数可能是rule中的解析函数,也可能是 parse_start_url函数)

如果设置了回调函数(parse_start_url()),那么首先用parse_start_url()处理response对象,

然后再交给process_results处理。返回cb_res的一个列表

if callback:

如果是parse调用的,则会解析成Request对象

如果是rule callback,则会解析成Item

cb_res = callback(response, **cb_kwargs) or ()
cb_res = self.process_results(response, cb_res)
for requests_or_item in iterate_spider_output(cb_res):
yield requests_or_item

如果需要跟进,那么使用定义的Rule规则提取并返回这些Request对象

if follow and self._follow_links:

返回每个Request对象

for request_or_item in self._requests_to_follow(response):
yield request_or_item

def _compile_rules(self):
def get_method(method):
if callable(method):
return method
elif isinstance(method, basestring):
return getattr(self, method, None)

self._rules = [copy.copy(r) for r in self.rules]
for rule in self._rules:
rule.callback = get_method(rule.callback)
rule.process_links = get_method(rule.process_links)
rule.process_request = get_method(rule.process_request)

def set_crawler(self, crawler):
super(CrawlSpider, self).set_crawler(crawler)
self._follow_links = crawler.settings.getbool('CRAWLSPIDER_FOLLOW_LINKS', True)

LinkExtractors

使用LinkExtractors 的目的: 提取链接。每个LinkExtractor有唯一的公共方法是 extract_links(),它接收一个 Response 对象,并返回一个 scrapy.link.Link 对象。
scrapy.linkextractors.LinkExtractor(
allow = (),
deny = (),
allow_domains = (),
deny_domains = (),
deny_extensions = None,
restrict_xpaths = (),
tags = ('a','area'),
attrs = ('href'),
canonicalize = True,
unique = True,
process_value = None
)

主要参数:
allow:满足括号中“正则表达式”的值会被提取,如果为空,则全部匹配。
deny:与这个正则表达式(或正则表达式列表)匹配的URL一定不提取。
allow_domains:会被提取的链接的domains。
deny_domains:一定不会被提取链接的domains。
restrict_xpaths:使用xpath表达式,和allow共同作用过滤链接。

rules

在rules中包含一个或多个Rule对象,每个Rule对爬取网站的动作定义了特定操作。如果多个rule匹配了相同的链接,则根据规则在本集合中被定义的顺序,第一个会被使用。

scrapy.spiders.Rule(
link_extractor,
callback = None,
cb_kwargs = None,
follow = None,
process_links = None,
process_request = None
)

link_extractor:是一个Link Extractor对象,用于定义需要提取的链接。
callback: 从link_extractor中每获取到链接时,参数所指定的值作为回调函数,该回调函数接受一个response作为其第一个参数。
注意:当编写爬虫规则时,避免使用parse作为回调函数。由于CrawlSpider使用parse方法来实现其逻辑,如果覆盖了parse方法,crawlspider将会运行失败。
follow:是一个布尔(boolean)值,指定了根据该规则从response提取的链接是否需要跟进。 如果callback为None,follow默认设置为True ,否则默认为False。
process_links:指定该spider中哪个的函数将会被调用,从link_extractor中获取到链接列表时将会调用该函数。该方法主要用来过滤。
process_request:指定该spider中哪个的函数将会被调用, 该规则提取到每个request时都会调用该函数。 (用来过滤request)

robots协议

Robots协议(也称为爬虫协议、机器人协议等)的全称是“网络爬虫排除标准”(Robots Exclusion Protocol),网站通过Robots协议告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取。robots.txt文件是一个文本文件。当一个搜索蜘蛛访问一个站点时,它会首先检查该站点根目录下是否存在robots.txt,如果存在,搜索机器人就会按照该文件中的内容来确定访问的范围;如果该文件不存在,所有的搜索蜘蛛将能够访问网站上所有没有被口令保护的页面。

User-agent: *  这里的代表的所有的搜索引擎种类,是一个通配符
Disallow: /admin/ 这里定义是禁止爬寻admin目录下面的目录
Disallow: /require/ 这里定义是禁止爬寻require目录下面的目录
Disallow: /ABC/ 这里定义是禁止爬寻ABC目录下面的目录
Disallow: /cgi-bin/.htm 禁止访问/cgi-bin/目录下的所有以".htm"为后缀的URL(包含子目录)。
Disallow: /
?* 禁止访问网站中所有包含问号 (?) 的网址
Disallow: /.jpg禁止抓取网页所有的.jpg格式的图片 Disallow:/ab/adc.html 禁止爬取ab文件夹下面的adc.html文件。 Allow: /cgi-bin/ 这里定义是允许爬寻cgi-bin目录下面的目录 Allow: /tmp 这里定义是允许爬寻tmp的整个目录 Allow: .htm 仅允许访问以".htm"为后缀的URL。
Allow: .gif$ 允许抓取网页和gif格式图片
Sitemap: 网站地图 告诉爬虫这个页面是网站地图
实例分析:淘宝网的 robots.txt文件
http://www.taobao.com/robots.txt

禁止robots协议将 ROBOTSTXT_OBEY = True改为False

Logging

Scrapy提供了log功能,可以通过 logging 模块使用。

可以修改配置文件settings.py,任意位置添加下面两行,效果会清爽很多。

LOG_ENABLED = True  # 开启
LOG_FILE = "TencentSpider.log" #日志文件名
LOG_LEVEL = "INFO" #日志级别

Log levels

  • Scrapy提供5层logging级别:
  • CRITICAL – 严重错误(critical)

  • ERROR – 一般错误(regular errors)

  • WARNING – 警告信息(warning messages)

  • INFO – 一般信息(informational messages)

  • DEBUG – 调试信息(debugging messages)

logging设置

通过在setting.py中进行以下设置可以被用来配置logging:

LOG_ENABLED

默认: True,启用logging

LOG_ENCODING

默认: ‘utf-8’,logging使用的编码

LOG_FILE

默认: None,在当前目录里创建logging输出文件的文件名

LOG_LEVEL

默认: ‘DEBUG’,log的最低级别

scrapy的日志模块已经被scrapy弃用,也可以使用python自带日志模块
import logging

LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s" # 设置输出格式
DATE_FORMAT = "%Y/%m/%d %H:%M:%S" # 设置时间格式
logging.basicConfig(filename='sina.log', filemode='a+', format=LOG_FORMAT, datefmt=DATE_FORMAT)

logging.warning('错误')

settings.py 设置抓取间隔

DOWNLOAD_DELAY = 0.25   # 设置下载间隔为250ms
练习:爬取糗事百科翻页爬取地址: https://www.qiushibaike.com/8hr/page/{}/
练习:爬取腾讯招聘网,翻页获取岗位名称,时间,招聘人数,并存入数据库 https://hr.tencent.com/position.php?keywords=&lid=2218&tid=87&start=0#a

Settings配置

Scrapy设置(settings)提供了定制Scrapy组件的方法。可以控制包括核心(core),插件(extension),pipeline及spider组件。

BOT_NAME

默认: 'scrapybot'

Scrapy项目实现的bot的名字(也为项目名称)。 这将用来构造默认 User-Agent,同时也用来log。

当您使用 startproject 命令创建项目时其也被自动赋值。

CONCURRENT_ITEMS

默认: 100

Item Processor(即 Item Pipeline) 同时处理(每个response的)item的最大值。

CONCURRENT_REQUESTS

默认: 16

Scrapy downloader 并发请求(concurrent requests)的最大值。

CONCURRENT_REQUESTS_PER_DOMAIN

默认: 8

对单个网站进行并发请求的最大值。

CONCURRENT_REQUESTS_PER_IP

默认: 0

对单个IP进行并发请求的最大值。如果非0,则忽略 CONCURRENT_REQUESTS_PER_DOMAIN 设定, 使用该设定。 也就是说,并发限制将针对IP,而不是网站。

该设定也影响 DOWNLOAD_DELAY: 如果 CONCURRENT_REQUESTS_PER_IP 非0,下载延迟应用在IP而不是网站上。

DEFAULT_REQUEST_HEADERS

DEFAULT_REQUEST_HEADERS = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8',
'Accept-Language': 'en',
}

Scrapy HTTP Request使用的默认header。由 DefaultHeadersMiddleware 产生。

DEPTH_LIMIT

默认: 0

爬取网站最大允许的深度(depth)值。如果为0,则没有限制。

DEPTH_PRIORITY

默认: 0

整数值。用于根据深度调整request优先级。

如果为0,则不根据深度进行优先级调整。

DEPTH_STATS

默认: True

是否收集最大深度数据。

DEPTH_STATS_VERBOSE

默认: False

是否收集详细的深度数据。如果启用,每个深度的请求数将会被收集在数据中。

DNSCACHE_ENABLED

默认: True

是否启用DNS内存缓存(DNS in-memory cache)。

DOWNLOADER

默认: 'scrapy.core.downloader.Downloader'

用于crawl的downloader.

DOWNLOADER_MIDDLEWARES

默认:: {}

保存项目中启用的下载中间件及其顺序的字典。

DOWNLOADER_MIDDLEWARES_BASE

默认:

{
'scrapy.contrib.downloadermiddleware.robotstxt.RobotsTxtMiddleware': 100,
'scrapy.contrib.downloadermiddleware.httpauth.HttpAuthMiddleware': 300,
'scrapy.contrib.downloadermiddleware.downloadtimeout.DownloadTimeoutMiddleware': 350,
'scrapy.contrib.downloadermiddleware.useragent.UserAgentMiddleware': 400,
'scrapy.contrib.downloadermiddleware.retry.RetryMiddleware': 500,
'scrapy.contrib.downloadermiddleware.defaultheaders.DefaultHeadersMiddleware': 550,
'scrapy.contrib.downloadermiddleware.redirect.MetaRefreshMiddleware': 580,
'scrapy.contrib.downloadermiddleware.httpcompression.HttpCompressionMiddleware': 590,
'scrapy.contrib.downloadermiddleware.redirect.RedirectMiddleware': 600,
'scrapy.contrib.downloadermiddleware.cookies.CookiesMiddleware': 700,
'scrapy.contrib.downloadermiddleware.httpproxy.HttpProxyMiddleware': 750,
'scrapy.contrib.downloadermiddleware.chunked.ChunkedTransferMiddleware': 830,
'scrapy.contrib.downloadermiddleware.stats.DownloaderStats': 850,
'scrapy.contrib.downloadermiddleware.httpcache.HttpCacheMiddleware': 900,
}

包含Scrapy默认启用的下载中间件的字典。 永远不要在项目中修改该设定.

DOWNLOADER_STATS

默认: True

是否收集下载器数据。

DOWNLOAD_DELAY

默认: 0

下载器在下载同一个网站下一个页面前需要等待的时间。该选项可以用来限制爬取速度, 减轻服务器压力。同时也支持小数:

DOWNLOAD_DELAY = 0.25    # 250 ms of delay

DOWNLOAD_TIMEOUT

默认: 180

下载器超时时间(单位: 秒)。

EXTENSIONS

默认:: {}

保存项目中启用的插件及其顺序的字典。

EXTENSIONS_BASE

默认:

{
'scrapy.contrib.corestats.CoreStats': 0,
'scrapy.webservice.WebService': 0,
'scrapy.telnet.TelnetConsole': 0,
'scrapy.contrib.memusage.MemoryUsage': 0,
'scrapy.contrib.memdebug.MemoryDebugger': 0,
'scrapy.contrib.closespider.CloseSpider': 0,
'scrapy.contrib.feedexport.FeedExporter': 0,
'scrapy.contrib.logstats.LogStats': 0,
'scrapy.contrib.spiderstate.SpiderState': 0,
'scrapy.contrib.throttle.AutoThrottle': 0,
}

可用的插件列表。需要注意,有些插件需要通过设定来启用。默认情况下, 该设定包含所有稳定(stable)的内置插件。

ITEM_PIPELINES

默认: {}

保存项目中启用的pipeline及其顺序的字典。该字典默认为空,值(value)任意。 不过值(value)习惯设定在0-1000范围内。

ITEM_PIPELINES = {
'mybot.pipelines.validate.ValidateMyItem': 300,
'mybot.pipelines.validate.StoreMyItem': 800,
}

ITEM_PIPELINES_BASE

默认: {}

保存项目中默认启用的pipeline的字典。 永远不要在项目中修改该设定,而是修改 ITEM_PIPELINES

LOG_ENABLED

默认: True

是否启用logging。

LOG_ENCODING

默认: 'utf-8'

logging使用的编码。

LOG_FILE

默认: None

logging输出的文件名。如果为None,则使用标准错误输出(standard error)。

LOG_LEVEL

默认: 'DEBUG'

log的最低级别。可选的级别有: CRITICAL、 ERROR、WARNING、INFO、DEBUG。更多内容请查看 Logging 。

LOG_STDOUT

默认: False

如果为 True ,进程所有的标准输出(及错误)将会被重定向到log中。例如, 执行 print 'hello' ,其将会在Scrapy log中显示。

MEMDEBUG_ENABLED

默认: False

是否启用内存调试(memory debugging)。

MEMDEBUG_NOTIFY

默认: []

如果该设置不为空,当启用内存调试时将会发送一份内存报告到指定的地址;否则该报告将写到log中。

样例:

MEMDEBUG_NOTIFY = ['user@example.com']

MEMUSAGE_ENABLED

默认: False

Scope: scrapy.contrib.memusage

是否启用内存使用插件。当Scrapy进程占用的内存超出限制时,该插件将会关闭Scrapy进程, 同时发送email进行通知。

MEMUSAGE_LIMIT_MB

默认: 0

Scope: scrapy.contrib.memusage

在关闭Scrapy之前所允许的最大内存数(单位: MB)(如果 MEMUSAGE_ENABLED为True)。 如果为0,将不做限制。

MEMUSAGE_NOTIFY_MAIL

默认: False

Scope: scrapy.contrib.memusage

达到内存限制时通知的email列表。

MEMUSAGE_NOTIFY_MAIL = ['user@example.com']

MEMUSAGE_REPORT

默认: False

Scope: scrapy.contrib.memusage

每个spider被关闭时是否发送内存使用报告。

MEMUSAGE_WARNING_MB

默认: 0

Scope: scrapy.contrib.memusage

在发送警告email前所允许的最大内存数(单位: MB)(如果 MEMUSAGE_ENABLED为True)。 如果为0,将不发送警告。

NEWSPIDER_MODULE

默认: ''

使用 genspider 命令创建新spider的模块。

NEWSPIDER_MODULE = 'mybot.spiders_dev'

REDIRECT_MAX_TIMES

默认: 20

定义request允许重定向的最大次数。超过该限制后该request直接返回获取到的结果。 对某些任务我们使用Firefox默认值。

REDIRECT_PRIORITY_ADJUST

默认: +2

修改重定向请求相对于原始请求的优先级。

ROBOTSTXT_OBEY

默认: False

Scope: scrapy.contrib.downloadermiddleware.robotstxt

如果启用,Scrapy将会尊重 robots.txt策略。

SCHEDULER

默认: 'scrapy.core.scheduler.Scheduler'

用于爬取的调度器。

SPIDER_CONTRACTS

默认:: {}

保存项目中启用用于测试spider的scrapy contract及其顺序的字典

SPIDER_CONTRACTS_BASE

默认:

{
'scrapy.contracts.default.UrlContract' : 1,
'scrapy.contracts.default.ReturnsContract': 2,
'scrapy.contracts.default.ScrapesContract': 3,
}

保存项目中默认启用的scrapy contract的字典。 永远不要在项目中修改该设定,而是修改SPIDER_CONTRACTS

SPIDER_MIDDLEWARES

默认:: {}

保存项目中启用的下载中间件及其顺序的字典。

SPIDER_MIDDLEWARES_BASE

默认:

{
'scrapy.contrib.spidermiddleware.httperror.HttpErrorMiddleware': 50,
'scrapy.contrib.spidermiddleware.offsite.OffsiteMiddleware': 500,
'scrapy.contrib.spidermiddleware.referer.RefererMiddleware': 700,
'scrapy.contrib.spidermiddleware.urllength.UrlLengthMiddleware': 800,
'scrapy.contrib.spidermiddleware.depth.DepthMiddleware': 900,
}

保存项目中默认启用的spider中间件的字典。 永远不要在项目中修改该设定,而是修改SPIDER_MIDDLEWARES

SPIDER_MODULES

默认: []

Scrapy搜索spider的模块列表。

SPIDER_MODULES = ['mybot.spiders_prod', 'mybot.spiders_dev']

STATS_CLASS

默认: 'scrapy.statscol.MemoryStatsCollector'

收集数据的类。该类必须实现 状态收集器(Stats Collector) API.

STATS_DUMP

默认: True

当spider结束时dump Scrapy状态数据 (到Scrapy log中)。

STATSMAILER_RCPTS

默认: []

spider完成爬取后发送Scrapy数据。

TELNETCONSOLE_ENABLED

默认: True

表明 telnet 终端 (及其插件)是否启用的布尔值。

TELNETCONSOLE_PORT

默认: [6023, 6073]

telnet终端使用的端口范围。如果设置为 None0 , 则使用动态分配的端口。

TEMPLATES_DIR

默认: scrapy模块内部的 templates

使用 startproject 命令创建项目时查找模板的目录。

URLLENGTH_LIMIT

默认: 2083

Scope: contrib.spidermiddleware.urllength

爬取URL的最大长度。

USER_AGENT

默认: "Scrapy/VERSION (+http://scrapy.org)"

爬取的默认User-Agent,除非被覆盖。

REACTOR_THREADPOOL_MAXSIZE

线程池数量,默认10条

Scrapy反反爬策略

通常反反爬主要有以下几个策略:

设置User-Agent(随机切换User-Agent,模拟不同用户的浏览器信息)
添加请求头的多种方式

方法1:

修改setting.py中的User-Agent

USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36'

方法2:

修改setting中的DEFAULT_REQUEST_HEADERS

DEFAULT_REQUEST_HEADERS = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8',
'Accept-Language': 'en',
'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36'
}

方法3:

在代码中修改。

class HeadervalidationSpider(scrapy.Spider):
name = 'headervalidation'
allowed_domains = ['helloacm.com']

重写start_requests

def start_requests(self):
header={'User-Agent':'ua'}
yield scrapy.Request(url='', headers=header, callback=self.parse)

def parse(self, response):
pass
禁用Cookies
也就是不启用cookies middleware,不向Server发送cookies,有些网站通过cookie的使用发现爬虫行为
可以通过COOKIES_ENABLED控制 CookiesMiddleware 开启或关闭
除非特殊需要,可以禁用cookies,防止某些网站根据Cookie来封锁爬虫。
COOKIES_ENABLED = False
设置延迟下载
防止访问过于频繁,设置为 2秒 或更高
DOWNLOAD_DELAY = 3
使用IP地址池
VPN和代理IP,现在大部分网站都反IP的

自定义中间件

process_request(self, request, spider)
当每个request通过下载中间件时,该方法被调用。

process_response(self, request, response, spider)
当下载器完成http请求,传递响应给引擎的时候调用
修改settings.py配置USER_AGENTS和PROXIES
# 添加USER_AGENTS:
USER_AGENTS = [
"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 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
"Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)",
"Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0",
"Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5"
]

添加代理IP设置PROXIES:

免费代理IP可以网上搜索(免费的不太稳定),或者付费购买一批可用的私密代理IP:

PROXIES = [
{'ip_port': '111.8.60.9:8123'},
{'ip_port': '101.71.27.120:80'},
{'ip_port': '122.96.59.104:80'},
{'ip_port': '122.224.249.122:8088'},
]
创建中间件类
# -- coding: utf-8 --
import random
from settings import USER_AGENTS
from settings import PROXIES

随机的User-Agent

class RandomUserAgent(object):
def process_request(self, request, spider):
useragent = random.choice(USER_AGENTS)
request.headers.setdefault("User-Agent", useragent)

随机代理IP

class RandomProxy(object):
def process_request(self, request, spider):
proxy = random.choice(PROXIES)
request.meta['proxy'] = "http://" + proxy['ip_port']
配置中间件
# 最后设置setting.py里的DOWNLOADER_MIDDLEWARES,添加自己编写的下载中间件类
DOWNLOADER_MIDDLEWARES = {

'mySpider.middlewares.MyCustomDownloaderMiddleware': 543,

'mySpider.middlewares.RandomUserAgent': 81,
'mySpider.middlewares.ProxyMiddleware': 100
}

文章来源于互联网:python爬虫–day07

发表评论