scrapy框架-媒体文件爬取-middleware
# 1.scrapy框架
- 框架:- 就是一个集成了各种功能且具有很强通用性(可以被应用在各种不同的需求中)的一个项目模板.
- scrapy 框架集成了哪些功能:
- 高性能的数据解析操作,持久化存储操作,高性能的数据下载的操作.
# 1.1 安装scrapy
pip3 install wheel
下载twisted http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
进入下载目录,执行 pip3 install Twisted‑17.1.0‑cp35‑cp35m‑win_amd64.whl
pip3 install pywin32
pip3 install scrapy
# 1.2 简单使用
scrapy创建需要在终端执行命令
- scrapy startproject proName 创建项目
- cd proNme 进入项目文件夹
- scrapy genspider spiderName www.xxx.com 创建一个爬虫文件
# 1.3 配置文件
不遵从robots协议
# Obey robots.txt rules ROBOTSTXT_OBEY = False
1
2进行UA伪装
USER_AGENT = '浏览器USER_AGENT'
1进行日志等级设定:
LOG_LEVEL = 'ERROR'
# 1.4 使用方法
import scrapy
class FirstSpider(scrapy.Spider):
# 爬虫文件的名称:爬虫文件的唯一标识(在spiders子目录下是可以创建多个爬虫文件)
name = 'first'
# 允许的域名,一般注释掉
allowed_domains = ['www.baidu.com']
# 起始的url列表:列表中存放的url会被scrapy自动的进行请求发送
start_urls = ['https://www.baidu.com/', 'https://www.sogou.com/']
# 用作于数据解析:将start_urls列表中对应的url请求成功后的响应数据进行解析
def parse(self, response):
print(response)
2
3
4
5
6
7
8
9
10
11
12
- 项目启动命令
- scrapy crawl pro_name
# 1.5 持久化存储
基于终端指令:
- 特性:只可以将parse方法的返回值存储到本地的磁盘文件中
- 存储指令: scrapy crawl spiderName -o filePath
class XiaopapaSpider(scrapy.Spider): name = 'qiubai' # allowed_domains = ['www.xxx.com'] start_urls = ['https://www.qiushibaike.com/text/'] # 基于终端指令的持久化存储操作 def parse(self, response): div_list = response.xpath('//*[@id="content-left"]/div') all_data = [] for div in div_list: # scrapy中的xpath返回的列表的列表元素一定是Selector对象,我们最终想要的解析的数据一定是存储在该对象中 # extract()将Selector对象中data参数的值取出 # author = div.xpath('./div[1]/a[2]/h2/text()')[0].extract() # 取第一个 author = div.xpath('./div[1]/a[2]/h2/text()').extract_first() # 也是取第一个 # 列表直接调用extract表示的是将extract作用到每一个列表元素中 content = div.xpath('./a[1]/div/span//text()').extract() content = ''.join(content) dic = {'author': author, 'content': content } all_data.append(dic) return all_data # response.xpath("xpath 路径") 返回的列表的列表元素是Selector对象,数据存在该对象当中 # extract()将Selector对象中data参数的值取出 # .extract_first() # 取第一个值 # 列表直接调用extract表示的是将extract作用到每一个列表元素中,返回的是一个列表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
基于管道:实现流程
1.数据解析 2.在item类中定义相关的属性 3.将解析的数据存储或者封装到一个item类型的对象(items文件中对应类的对象) 4.向管道提交item 5.在管道文件的process_item方法中接收item进行持久化存储 6.在配置文件中开启管道
# 管道中需要注意的细节: - 配置文件中开启管道对应的配置是一个字典,字典中的键值表示的就是某一个管道 - 在管道对应的源文件中其实可以定义多个管道类。一个管道类对应的是一种形式的持久化存储 - 在process_item方法中的return item表示的是将item提交给下一个即将被执行的管道类 - 爬虫文件通过yield item只可以将item提交给第一个(优先级最高)被执行的管道
1
2
3
4
5将同一份数据持久化到不同的平台中
- 分析:
- 1.管道文件中的一个管道类负责数据的一种形式的持久化存储
- 2.爬虫文件向管道提交的item只会提交给优先级最高的那一个管道类
- 3.在管道类的process_item中的return item表示的是将当前管道接收的item返回/提交给 下一个即将被执行的管道类
# 基于管道的持久化存储 # 爬虫.py文件, def parse(self, response): div_list = response.xpath('//*[@id="content-left"]/div') all_data = [] for div in div_list: #scrapy中的xpath返回的列表的列表元素一定是Selector对象,我们最终想要的解析的 #数据一定是存储在该对象中 #extract()将Selector对象中data参数的值取出 # author = div.xpath('./div[1]/a[2]/h2/text()')[0].extract() author = div.xpath('./div[1]/a[2]/h2/text()').extract_first() #列表直接调用extract表示的是将extract作用到每一个列表元素中 content = div.xpath('./a[1]/div/span//text()').extract() content = ''.join(content) #将解析的数据存储到item对象 item = QiubaiproItem() item['author'] = author item['content'] = content #将item提交给管道 yield item #item一定是提交给了优先级最高的管道类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21- items.py文件
# items.py文件 class QiubaiproItem(scrapy.Item): author = scrapy.Field() #Field可以将其理解成是一个万能的数据类型 content = scrapy.Field()
1
2
3
4- pipelines.py文件
- 存储到不同的数据平台中
# pipelines.py文件 #存储到文件中 class QiubaiproPipeline(object): fp = None def open_spider(self,spider): # 重写父类方法,只会执行一次,打开文件 print('开始爬虫!') self.fp = open('qiushibaike.txt','w',encoding='utf-8') #使用来接收爬虫文件提交过来的item,然后将其进行任意形式的持久化存储 #参数item:就是接收到的item对象 #该方法每接收一个item就会调用一次 def process_item(self, item, spider): author = item['author'] content= item['content'] self.fp.write(author+':'+content+'\n') return item #item是返回给了下一个即将被执行的管道类 def close_spider(self,spider): # 重写父类方法,只会执行一次,关闭文件 print('结束爬虫!') self.fp.close() #负责将数据存储到mysql class MysqlPL(object): conn = None cursor = None def open_spider(self,spider): self.conn = pymysql.Connect(host='127.0.0.1', port=3306, user='root', password='123', db='spider', charset='utf8') print(self.conn) def process_item(self,item,spider): author = item['author'] content = item['content'] sql = 'insert into qiubai values ("%s","%s")'%(author,content) self.cursor = self.conn.cursor() try: self.cursor.execute(sql) self.conn.commit() except Exception as e: print(e) self.conn.rollback() return item def close_spider(self,spider): self.cursor.close() self.conn.close() # 存到redis class RedisPL(object): conn = None def open_spider(self,spider): self.conn = Redis(host='127.0.0.1',port=6379) print(self.conn) def process_item(self,item,spider): self.conn.lpush('all_data',item) #注意:如果将字典写入redis报错:pip install -U redis==2.10.6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59- settings文件
- 注册定义的管道
ITEM_PIPELINES = { 'qiubaiPro.pipelines.QiubaiproPipeline': 300, # 300表示的是优先级,数字越小,优先级就越大 'qiubaiPro.pipelines.MysqlPL': 301, 'qiubaiPro.pipelines.RedisPL': 302, }
1
2
3
4
5- 分析:
# 1.6 发送请求
1.6.1 自动请求发送:
```python
def start_requests(self): for url in self.start_urls: yield scrapy.Request(url,callback=self.parse) ```
1.6.2 手动发送请求:
- 在scrapy中如何进行手动请求发送(GET)
- 使用场景:爬取多个页码对应的页面源码数据
- yield scrapy.Request(url,callback)
- 在scrapy中如何进行手动请求发送(POST) data = { #post请求的请求参数 'kw':'aaa' } yield scrapy.FormRequest(url,formdata=data,callback)
#将多个页码对应的页面数据进行爬取和解析的操作
url = 'https://www.qiushibaike.com/text/page/%d/'#通用的url模板
pageNum = 1
#parse第一次调用表示的是用来解析第一页对应页面中的段子内容和作者
def parse(self, response):
div_list = response.xpath('//*[@id="content-left"]/div')
all_data = []
for div in div_list:
author = div.xpath('./div[1]/a[2]/h2/text()').extract_first()
# 列表直接调用extract表示的是将extract作用到每一个列表元素中
content = div.xpath('./a[1]/div/span//text()').extract()
content = ''.join(content)
# 将解析的数据存储到item对象
item = QiubaiproItem()
item['author'] = author
item['content'] = content
# 将item提交给管道
yield item # item一定是提交给了优先级最高的管道类
if self.pageNum <= 5:
self.pageNum += 1
new_url = format(self.url%self.pageNum)
#手动请求(get)的发送
yield scrapy.Request(new_url,callback=self.parse) # 递归调用parse方法
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 1.7 scrapy五大核心组件的工作流程
- 引擎(Scrapy)
- 用来处理整个系统的数据流处理, 触发事务(框架核心)
- 调度器(Scheduler)
- 用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址
- 下载器(Downloader)
- 用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)
- 爬虫(Spiders)
- 爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面
- 项目管道(Pipeline)
- 负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。
![1567386219292](C:\Users\big cattle\AppData\Roaming\Typora\typora-user-images\1567386219292.png)
# 2. scrapy 图片数据的爬取
基于scrapy进行图片数据的爬取:
- 在爬虫文件中只需要解析提取出图片地址,然后将地址提交给管道
- 配置文件中写入文件存储位置:IMAGES_STORE = './imgsLib'
- 在管道文件中进行管道类的制定:
- 1.from scrapy.pipelines.images import ImagesPipeline
- 2.将管道类的父类修改成ImagesPipeline
- 3.重写父类的三个方法
校花网爬取示例
spider.py文件
import scrapy from imgspider.items import ImgspiderItem class ImgSpiderSpider(scrapy.Spider): name = 'img_spider' # allowed_domains = ['www.xxx.com'] start_urls = ['http://www.521609.com/daxuemeinv/'] url = 'http://www.521609.com/daxuemeinv/list8%d.html' pageNum = 1 def parse(self, response): li_list = response.xpath('//*[@id="content"]/div[2]/div[2]/ul/li') # 拼接图片url for li in li_list: print(self.pageNum) img_src = 'http://www.521609.com' + li.xpath('./a[1]/img/@src').extract_first() item = ImgspiderItem() item['src'] = img_src yield item if self.pageNum < 3: self.pageNum += 1 new_url = format(self.url % self.pageNum) yield scrapy.Request(new_url, callback=self.parse)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25pipelines.py文件
import scrapy from imgspider.items import ImgspiderItem class ImgSpiderSpider(scrapy.Spider): name = 'img_spider' # allowed_domains = ['www.xxx.com'] start_urls = ['http://www.521609.com/daxuemeinv/'] url = 'http://www.521609.com/daxuemeinv/list8%d.html' pageNum = 1 def parse(self, response): li_list = response.xpath('//*[@id="content"]/div[2]/div[2]/ul/li') # 拼接图片url for li in li_list: print(self.pageNum) img_src = 'http://www.521609.com' + li.xpath('./a[1]/img/@src').extract_first() item = ImgspiderItem() item['src'] = img_src yield item if self.pageNum < 3: self.pageNum += 1 new_url = format(self.url % self.pageNum) yield scrapy.Request(new_url, callback=self.parse)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 3.请求传参实现深度爬取
请求传参:
实现深度爬取:爬取多个层级对应的页面数据
使用场景:爬取的数据没有在同一张页面中
在手动请求的时候传递item:yield scrapy.Request(url,callback,meta={'item':item})
- 将meta这个字典传递给callback
- 在callback中接收meta:item = response.meta['item']
def parse(self, response): li_list = response.xpath('/html/body/div[1]/div/div/div/div[2]/ul/li') for li in li_list: title = li.xpath('./div[1]/a/@title').extract_first() detail_url = 'https://www.4567tv.tv' + li.xpath('./div[1]/a/@href').extract_first() item = MoviespiderItem() item['title'] = title # meta参数是一个字典,该字典就可以传递给callback指定的回调函数 yield scrapy.Request(detail_url, callback=self.parse_detail, meta={"item": item}) def parse_detail(self, response): # 接收meta:response.meta item = response.meta['item'] desc = response.xpath('/html/body/div[1]/div/div/div/div[2]/p[5]/span[2]/text()').extract_first() item["desc"] = desc yield item
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 4.下载中间件的应用
- scrapy中间件有:-爬虫中间件,下载中间件
- 下载中间件应用较多
- 下载中间件:
- 作用:批量拦截请求和响应
- 拦截请求:
- UA伪装:将所有的请求尽可能多的设定成不同的请求载体身份标识
- request.headers['User-Agent'] = 'xxx'
- 代理操作:request.meta['proxy'] = 'http://ip:port'
- 拦截响应:篡改响应数据或者直接替换响应对象
# 4.1 拦截请求中间件
作用:
- UA伪装:将所有的请求尽可能多的设定成不同的请求载体身份标识
- request.headers['User-Agent'] = 'xxx'
- 代理操作:request.meta['proxy'] = 'http://ip:port'
- UA伪装:将所有的请求尽可能多的设定成不同的请求载体身份标识
爬取4567视频网示例:
- spider.py文件
import scrapy from moviespider.items import MoviespiderItem class MovieSpiderSpider(scrapy.Spider): name = 'movie_spider' # allowed_domains = ['https://www.4567tv.tv/index.php/vod/show/class/动作/id/1.html'] start_urls = ['https://www.4567tv.tv/index.php/vod/show/class/动作/id/1.html'] url = 'https://www.4567tv.tv/index.php/vod/show/class/动作/id/1/page/%d.html' pageNum = 1 def parse(self, response): li_list = response.xpath('/html/body/div[1]/div/div/div/div[2]/ul/li') for li in li_list: title = li.xpath('./div[1]/a/@title').extract_first() detail_url = 'https://www.4567tv.tv' + li.xpath('./div[1]/a/@href').extract_first() item = MoviespiderItem() item['title'] = title # meta参数是一个字典,该字典就可以传递给callback指定的回调函数 yield scrapy.Request(detail_url, callback=self.parse_detail, meta={"item": item}) def parse_detail(self, response): # 接收meta:response.meta item = response.meta['item'] desc = response.xpath('/html/body/div[1]/div/div/div/div[2]/p[5]/span[2]/text()').extract_first() item["desc"] = desc yield item
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26items.py
- 创建title和desc的属性
pipelines.py文件
- 存储
middleware.py
- downloadmiddleware文件
from scrapy import signals import random 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", ] # 常见浏览器user_agent PROXY_http = [ '153.180.102.104:80', ] PROXY_https = [ '120.83.49.90:9000', ] class MoviespiderDownloaderMiddleware(object): # 拦截正常的请求,参数request就是拦截到的请求对象 def process_request(self, request, spider): print('i am process_request()') # 实现:将拦截到的请求尽可能多的设定成不同的请求载体身份标识 request.headers['User-Agent'] = random.choice(user_agent_list) # 代理操作 if request.url.split(':')[0] == 'http': request.meta['proxy'] = 'http://' + random.choice(PROXY_http) # http://ip:port else: request.meta['proxy'] = 'https://' + random.choice(PROXY_https) # http://ip:port return # 拦截响应:参数response就是拦截到的响应 def process_response(self, request, response, spider): print('i am process_response()') return response def process_exception(self, request, exception, spider): print('i am process_exception()') # 拦截到异常的请求然后对其进行修正,然后重新进行请求发送 # 代理操作 if request.url.split(':')[0] == 'http': request.meta['proxy'] = 'http://' + random.choice(PROXY_http) # http://ip:port else: request.meta['proxy'] = 'https://' + random.choice(PROXY_https) # http://ip:port return request # 将修正之后的请求进行重新发送
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
常用浏览器user_agent
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" ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 4.2 拦截响应中间件
作用:拦截响应可以篡改响应数据或者直接替换响应对象
selenium在scrapy中的应用:
- 实例化浏览器对象:写在爬虫类的构造方法中
- 关闭浏览器:爬虫类中的closed(self,spider)关闭浏览器
- 在中间件中执行浏览器自动化的操作
示例:
需求; 爬取网易新闻的国内,国际,军事,航空,无人机这五个板块下对应的新闻标题和内容(数据是动态加载的)
spider.py文件
# -*- coding: utf-8 -*- import scrapy from selenium import webdriver from wangyinews.item import WangyinewsItem class NewsSpider(scrapy.Spider): name = 'news' # allowed_domains = ['www.wangyi.com'] start_urls = ['https://news.163.com'] five_model_urls = [] bro = webdriver.Chrome(executable_path=r'D:\教学视频\python 爬虫\tools\chromedriver.exe') # 用来解析五个板块对应的url,然后对其进行手动请求发送 def parse(self, response): model_index = [3, 4, 6, 7, 8] li_list = response.xpath('//*[@id="index2016_wrap"]/div[1]/div[2]/div[2]/div[2]/div[2]/div/ul/li') for index in model_index: li = li_list[index] # 获取了五个板块对应的url model_url = li.xpath('./a/@href').extract_first() self.five_model_urls.append(model_url) # 对每一个板块的url进行手动i请求发送 yield scrapy.Request(model_url, callback=self.parse_model) # 解析每一个板块页面中的新闻标题和新闻详情页的url # 问题:response(不满足需求的response)中并没有包含每一个板块中动态加载出的新闻数据 def parse_model(self, response): div_list = response.xpath('/html/body/div[1]/div[3]/div[4]/div[1]/div/div/ul/li/div/div') for div in div_list: title = div.xpath('./div/div[1]/h3/a/text()').extract_first() detail_url = div.xpath('./div/div[1]/h3/a/@href').extract_first() item = WangyinewsItem() item['title'] = title # 对详情页发起请求解析出新闻内容 yield scrapy.Request(detail_url, callback=self.parse_new_content, meta={'item': item}) # 获取内容详情 def parse_new_content(self, response): item = response.meta["item"] content = response.xpath('//*[@id="endText"]//text()').extract() item["content"] = content yield item # 最后执行,关闭bro def close(self, spider): self.bro.quit()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47items.py
- 创建title和desc的属性
pipelines.py文件
- 存储
middleware.py文件:
# -*- coding: utf-8 -*- # Define here the models for your spider middleware # # See documentation in: # https://docs.scrapy.org/en/latest/topics/spider-middleware.html from time import sleep from scrapy import signals from scrapy.http import HtmlResponse class WangyinewsDownloaderMiddleware(object): def process_request(self, request, spider): return None def process_response(self, request, response, spider): # spider就是爬虫文件中爬虫类实例化的对象 # 进行所有响应对象的拦截 # 1.将所有的响应中那五个不满足需求的响应对象找出 # 1.每一个响应对象对应唯一一个请求对象 # 2.如果我们可以定位到五个响应对应的请求对象后,就可以通过该i请求对象定位到指定的响应对象 # 3.可以通过五个板块的url定位请求对象 # 总结: url==》request==》response # 2.将找出的五个不满足需求的响应对象进行修正(替换) # spider.five_model_urls:五个板块对应的url bro = spider.bro if request.url in spider.five_model_urls: bro.get(request.url) sleep(1) page_text = bro.page_source # 包含了动态加载的新闻数据 # 如果if条件程利则该response就是五个板块对应的响应对象 new_responde = HtmlResponse(url=request.url, body=page_text, encoding="utf-8", request=request) return new_responde return response def process_exception(self, request, exception, spider): pass
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 5.提高scrapy爬取效率配置
#增加并发:
默认scrapy开启的并发线程为32个,可以适当进行增加。在settings配置文件中修改CONCURRENT_REQUESTS = 100值为100,并发设置成了为100。
#降低日志级别:
在运行scrapy时,会有大量日志信息的输出,为了减少CPU的使用率。可以设置log输出信息为INFO或者ERROR即可。在配置文件中编写:LOG_LEVEL = ‘INFO’。
#禁止cookie:
如果不是真的需要cookie,则在scrapy爬取数据时可以禁止cookie从而减少CPU的使用率,提升爬取效率。在配置文件中编写:COOKIES_ENABLED = False。
#禁止重试:
对失败的HTTP进行重新请求(重试)会减慢爬取速度,因此可以禁止重试。在配置文件中编写:RETRY_ENABLED = False。
#减少下载超时:
如果对一个非常慢的链接进行爬取,减少下载超时可以能让卡住的链接快速被放弃,从而提升效率。在配置文件中进行编写:DOWNLOAD_TIMEOUT = 10 超时时间为10s。
2
3
4
5
6
7
8
9
10
11
12
13
14