爬⾍之scrapy框架
⼀、认识scrapy框架
何为框架,就相当于⼀个封装了很多功能的结构体,它帮我们把主要的结构给搭建好了,我们只需往⾻架⾥添加内容就⾏。scrapy框架是⼀个为了爬取⽹站数据,提取数据的框架,我们熟知爬⾍总共有四⼤部分,请求、响应、解析、存储,scrapy框架都已经搭建好了。scrapy是基于twisted框架开发⽽来,twisted是⼀个流⾏的事件驱动的python⽹络框架,scrapy使⽤了⼀种⾮阻塞的代码实现并发的,结构如下:
1、引擎(EGINE)
引擎负责控制系统所有组件之间的数据流,并在某些动作发⽣时触发事件。有关详细信息,请参见上⾯的数据流部分。
2、调度器(SCHEDULER)
⽤来接受引擎发过来的请求, 压⼊队列中, 并在引擎再次请求的时候返回. 可以想像成⼀个URL的优先级队列, 由它来决定下⼀个要抓取的⽹址是什么, 同时去除重复的⽹址
3、下载器(DOWLOADER)
⽤于下载⽹页内容, 并将⽹页内容返回给EGINE,下载器是建⽴在twisted这个⾼效的异步模型上的
4、爬⾍(SPIDERS)
SPIDERS是开发⼈员⾃定义的类,⽤来解析respons,并且提取items,或者发送新的请求
5、项⽬管道(ITEM PIPLINES)
在items被提取后负责处理它们,主要包括清理、验证、持久化(⽐如存到数据库)等操作
下载器中间件(Downloader Middlewares)位于Scrapy引擎和下载器之间,主要⽤来处理从EGINE传到DOWLOADER的请求request,已经从DOWNLOADER传到EGINE的响应respon,
你可⽤该中间件做以下⼏件事:
(1) process a request just before it is nt to the Downloader (i.e. right before Scrapy nds the request to the website);
(2) change received respon before passing it to a spider;
国家考试中心网 (3) nd a new Request instead of passing received respon to a spider;
(4) pass respon to a spider without fetching a web page;
(5) silently drop some requests.
6、爬⾍中间件(Spider Middlewares)
位于EGINE和SPIDERS之间,主要⼯作是处理SPIDERS的输⼊(即respons)和输出(即requests)
1,模块下载
Windows:
a. pip3 install wheel
b. 下载twisted www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
c. 进⼊下载⽬录,执⾏ pip3 install Twisted‑17.1.0‑cp35‑cp35m‑win_amd64.whl
d. pip3 install pywin32
e. pip3 install scrapy
切记按照从上往下的顺序执⾏
2,开启⼀个scrapy项⽬
1,新建⼀个项⽬
在pycharm的终端⾥输⼊:scrapy startproject 项⽬名称
构建了⼀个如下的⽂件⽬录:
project_name/
scrapy.cfg:
project_name/
__init__.py
items.py
pipelines.py
ttings.py
spiders/
__init__.py
scrapy.cfg 项⽬的主配置信息。(真正爬⾍相关的配置信息在ttings.py⽂件中)
items.py 设置数据存储模板,⽤于结构化数据,如:Django的Model
pipelines 数据持久化处理
ttings.py 配置⽂件,如:递归的层数、并发数,延迟下载等
spiders 爬⾍⽬录,如:创建⽂件,编写爬⾍解析规则
2,新建⼀个爬⾍程序
也是在pycharm的终端下输⼊:cd 项⽬名称#进⼊项⽬⽬录下
再输⼊:scrapy genspider 爬⾍程序名称爬⾍程序的起始url
此时就会在第⼆层的project_name⽂件夹下创建⼀个spider⽂件夹,spider⽂件夹下就会有⼀个‘爬⾍应⽤程序名字.py的⽂件’,如下:
project_name:
wudaproject_name:
spider:
app_name.py
此时app_name.py:
import scrapy
class QiubaiSpider(scrapy.Spider):
name = 'qiubai'#应⽤名称
#允许爬取的域名(如果遇到⾮该域名的url则爬取不到数据)
allowed_domains = ['/'] #我们⼀般情况下都会把给注释掉,
#起始爬取的url
start_urls = ['/']
#访问起始URL并获取结果后的回调函数,该函数的respon参数就是向起始的url发送请求后,获取的响应对象.该函数返回值必须为可迭代对象或者NUll
sarcastic
def par(lf, respon):
) #获取字符串类型的响应内容
print(respon.body)#获取字节类型的相应内容
3,修改ttings.py配置⽂件
修改内容及其结果如下:
19⾏:USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'#伪装请求载体⾝份
22⾏:ROBOTSTXT_OBEY = Fal #可以忽略或者不遵守robots协议
4,运⾏爬⾍程序
在pycharm终端⾥输⼊:scrapy crawl 爬⾍程序名称#这样就执⾏爬⾍程序了,这种情况下是要打印⽇志的
scrapy crawl 爬⾍程序名称 --nolog #这样就不会打印⽇志
还有⼀种⽅式:在最外层的project_name⽂件下新建⼀个start.py⽂件,名字随便写,在⽂件⾥写⼊:
dline import execute
execute(['scrapy', 'crawl', '爬⾍程序名字','--nolog'])
从此以后,我们每次只需要运⾏start⽂件,就可以让程序跑起来
⼆、请求、响应、解析
这三个功能的实现主要就是在爬⾍程序下,我这⾥以爬取⽹易新闻为例⼦。
1,项⽬要求
我此次项⽬的功能是:爬取⽹易新闻下的国内、国际、军事、航空的的所有新闻。
第⼀步:
第⼆步:点击进⼊四个板块
第三步:点击每条新闻,拿到每条新闻的标题,url,图⽚的url,所属的板块,关键字,内容
2,新建项⽬
在终端⾥依次输⼊:
scrapy startproject WY #Demo是我的项⽬名称
cd WY #进⼊我的项⽬环境下
scrapy genspider wangyi #创建我的⽹易爬⾍程序
3,编写wangyi.py代码
import scrapy
class WangyiSpider(scrapy.Spider):
name = 'wangyi'
# allowed_domains = ['']
start_urls = ['/'] #这是爬取⽹页的第⼀个url,然后回调par函数,并把返回值给回调函数
def par(lf, respon): #接收到第⼀次请求的响应好听的摇滚
a_list=respon.xpath('//div[@class="index_head"]//li/a') #利⽤xpath进⾏数据解析
l1=[3,4,6,7]
for i in l1:
link=a_list[i].xpath('./@href').extract_first() #这是拿到每个板块的url
genre=a_list[i].xpath('./text()').extract_first() #这是拿到了每个板块的名字
request=scrapy.Request(url=link,callback=lf.par_one) #这是向每个板块发送请求,然后把响应给回调函数par_one
yield request
守护甜心36def par_one(lf,respon): #拿到板块页⾯响应
div_list=respon.xpath('//div[@class="ndi_main"]/div') #这是拿到每条新闻的div标签
for div in div_list: #循环所有的新闻
url=div.xpath('.//a[@class="na_pic"]/@href').extract_first() #拿到每条新闻的url
title=div.xpath('.//a[@class="na_pic"]/img/@alt').extract_first() #拿到每条新闻的title
img_url=div.xpath('.//a[@class="na_pic"]/img/@src').extract_first() #拿到每条新闻的图⽚的url
key_list=div.xpath('.//div[@class="keywords"]//text()').extract() #拿到每条新闻的关键字列表
keyword_list=[]
for key in range(len(key_list)):
if (key+1) % 2 ==0:
fool什么意思
keyword_list.append(key_list[key])
keywords=','.join(keyword_list) #这是构建了每条新闻的关键字
request = scrapy.Request(url=url, callback=lf.par_two) #这是向没条新闻的url发送请求,把请求响应给par_two回调函数
yield request
def par_two(lf,respon):
content_list=respon.xpath('//div[@id="endText"]/p//text()').extract() #这是新闻内容,列表形式
content=''
for value in content_list:
content+=value.strip() #构建每条新闻的内容
以上的代码就能拿到想要的数据,但是哈,我在打印每条新闻时,好像并没有数据,这是咋回事呢,仔细检查代码,可以确定是每个板块的请求是发出去了,par_one也是接收到响应的,但好像
响应内容并不全⾯,于是我猜测应该是页⾯加载的问题,当我们给每个板块发送请求后,马上拿到的并不是页⾯的所有内容,有些js代码还没执⾏。对于这种问题,在我们之前的爬⾍过程也遇到了,可以通过lenium模块来解决。
三、lenium模块在scrapy框架的实现
在爬⾍过程中,对于动态加载的页⾯,我们可以使⽤lenium模块来解决,实例化⼀个浏览器对象,然后控制浏览器发送请求,等待页⾯内容加载完毕后,再获取页⾯信息。
1,lenium模块在scrapy框架中实现原理
当引擎将国内板块url对应的请求提交给下载器后,下载器进⾏⽹页数据的下载,然后将下载到的页⾯数据,封装到respon中,提交给引擎,引擎将respon在转交给Spiders。Spiders接受到的respon对象中存储的页⾯数据⾥是没有动态加载的新闻数据的。要想获取动态加载的新闻数据,则需要在下载中间件中对下载器提交给引擎的respon响应对象进⾏拦截,切对其内部存储的页⾯数据进⾏篡改,修改成携带了动态加载出的新闻数据,然后将被篡改的respon对象最终交给Spiders进⾏解析操作
2,lenium的使⽤流程
重写爬⾍⽂件的构造⽅法,在该⽅法中使⽤lenium实例化⼀个浏览器对象(因为浏览器对象只需要被实例化⼀次)
重写爬⾍⽂件的clod(lf,spider)⽅法,在其内部关闭浏览器对象。该⽅法是在爬⾍结束时被调⽤
重写下载中间件的process_respon⽅法,让该⽅法对响应对象进⾏拦截,并篡改respon中存储的页⾯数据
在配置⽂件中开启下载中间件
3,代码实现
3.1 wangyi.py
from lenium import webdriver
class WangyiSpider(scrapy.Spider):
def__init__(lf): #这是构造⽅法中,实例化⼀个浏览器对象
lf.driver=webdriver.Chrome(r'E:\Google\Chrome\')
def clo(lf,spider): #这个⽅法会在整个程序结束时执⾏,从⽽把浏览器对象给关闭
lf.driver.clo()
在上⾯的wangyi.py⽂件中加⼊这些代码就⾏
3.2 拦截响应,并篡改响应,在中间件中实现,middlewares.py
from scrapy.http import HtmlRespon
class WyDownloaderMiddleware(object):
#不管是什么请求,返回的响应对象都会经过这个函数
def process_respon(lf, request, respon, spider):
#request:响应对象对应的请求对象,reqeust.url就可以拿到本次请求的路径
#respon:拦截的响应对象
#spider:爬⾍⽂件中对应的爬⾍类的实例,spider.driver就可以拿到实例化的浏览器对象
#这是做了⼀个要⽤浏览器对象发送请求的⽩名单列表
allow_list=['/domestic/','/world/','/','/air/']
auts
#如果,这次请求的路径在⽩名单中,就把响应给拦截,然后⽤浏览器对象重新发送这个请求,然后拿到页⾯信息,再把拿到页⾯信息封装到⼀个响应对象⾥,然后才返回if request.url in allow_list:
#这是⼀个隐式等待
spider.driver.implicitly_wait(10)
(request.url)
#这是利⽤浏览器对象实现⼀个把滚动条拿到最下⾯的js过程
js = 'window.scrollTo(0,document.body.scrollHeight)'
ute_script(js)
#获取当前页⾯上的内容
res=spider.driver.page_source
#把页⾯上的内容封装到⼀个响应体对象⾥,并返回
return HtmlRespon(url=request.url,body=res,encoding='utf_8',request=request)
#如果本次请求不在⽩名单上,就不⽤拦截,不做任何处理
4,完成tting.py⽂件的修改
#放开中间件,让中间件⽣效
DOWNLOADER_MIDDLEWARES = {
'wangyiPro.middlewares.WangyiproDownloaderMiddleware': 543,
}
四、数据存储
1,基于终端指令的持久化存储
保证爬⾍⽂件的par⽅法中有可迭代类型对象(通常为列表or字典)的返回,该返回值可以通过终端指令的形式写⼊指定格式的⽂件中进⾏持久化操作
执⾏输出指定格式进⾏存储:将爬取到的数据写⼊不同格式的⽂件中进⾏存储
scrapy crawl 爬⾍名称 -o xxx.json
scrapy crawl 爬⾍名称 -l
scrapy crawl 爬⾍名称 -o xxx.csv
2,基于管道的持久化存储
基于管道的持久化存储,主要依靠scrapy框架的item.py和pipelines.py⽂件
item.py:数据结构模板⽂件,定义数据属性
pipelines.py:管道⽂件,接收数据(item),进⾏持久化操作
整个流程:
1,爬⾍⽂件爬取到数据后,把数据赋给item对象
2,使⽤yield关键字将item对象提交给pipelines管道
3,在管道⽂件中的process_item⽅法接收item对象,然后把item对象存储
4,在tting中开启管道
2.1 完成item.py⽂件的书写,也就是定义数据属性cornwall
import scrapy
class WyItem(scrapy.Item):
genre=scrapy.Field() #所属板块
title=scrapy.Field() #标题
url=scrapy.Field() #链接
img_url=scrapy.Field() #图⽚链接
keywords=scrapy.Field() #关键字
content=scrapy.Field() #全部内容
对于本次爬取的⽹易新闻我只存储这6个信息
2.2 完善wangyi.spider爬⾍程序
import scrapy
from WY.items import WyItem
from lenium import webdriver class WangyiSpider(scrapy.Spider):
name = 'wangyi'
start_urls = ['/']
def__init__(lf):
lf.driver=webdriver.Chrome(r'E:\Google\Chrome\')
def par(lf, respon):
a_list=respon.xpath('//div[@class="index_head"]//li/a')
l1=[3,4,6,7]
for i in l1:
link=a_list[i].xpath('./@href').extract_first()
#在这实例化item对象
item=WyItem()
genre=a_list[i].xpath('./text()').extract_first()
#把板块名字赋给item对象
item['genre']=genre
#在发送请求的同时,完成⼀个请求传参,也就是把item对象传递给回调函数,在回调函数也可以使⽤item对象‘meta={'item':item}’
request=scrapy.Request(url=link,callback=lf.par_one,meta={'item':item})
yield request
def par_one(lf,respon):
div_list=respon.xpath('//div[@class="ndi_main"]/div')
#取出item对象
a['item']
for div in div_list:
url=div.xpath('.//a[@class="na_pic"]/@href').extract_first()
title=div.xpath('.//a[@class="na_pic"]/img/@alt').extract_first()
img_url=div.xpath('.//a[@class="na_pic"]/img/@src').extract_first()
key_list=div.xpath('.//div[@class="keywords"]//text()').extract()
keyword_list=[]
for key in range(len(key_list)):
if (key+1) % 2 ==0:
keyword_list.append(key_list[key])
keywords=','.join(keyword_list)
#把拿到的数据赋给item对象
item['url']=url
item['title']=title
item['img_url']=img_url
item['keywords']=keywords
#在这⼜把item对象传递给了下⼀个回调函数
request = scrapy.Request(url=url, callback=lf.par_two, meta={'item': item})
yield request
def par_two(lf,respon):
a['item']
content_list=respon.xpath('//div[@id="endText"]/p//text()').extract()
content=''
for value in content_list:
content+=value.strip()
item['content']=content
yield item
def clo(lf,spider):
lf.driver.clo()
注意:回调函数的返回值为⼀个请求对象时,会把响应给回调函数,从⽽执⾏对应的回调函数;但当回调函数的返回值为item对象时,它会执⾏到pipelines.py⽂件,并把item对象传给process_item⽅法,并执⾏这⽅法
2.3 pipelines.py⽂件代码的实现,也就是真正的存储过程
1)存储在⽂件中
class WyFilePipeline(object):
#构造⽅法
def__init__(lf):
lf.fp = None #定义⼀个⽂件描述符属性
#下列都是在重写⽗类的⽅法:
def open_spider(lf,spider):
print('爬⾍开始')
lf.fp = open('./', 'w')
#因为该⽅法会被执⾏调⽤多次,所以⽂件的开启和关闭操作写在了另外两个只会各⾃执⾏⼀次的⽅法中。
def process_item(lf, item, spider):
#将爬⾍程序提交的item进⾏持久化存储
lf.fp.write(item['author'] + ':' + item['content'] + '\n')
return item
#结束爬⾍时,执⾏⼀次
def clo_spider(lf,spider):
lf.fp.clo()
print('爬⾍结束')
tting配置
#开启管道
ITEM_PIPELINES = {
'WY.pipelines.WyFilePipeline': 300,
}
2)存储在mongodb数据库中
import pymongo
class WyMongodbPipeline(object):
def open_spider(lf,spider):
#连接mongodb数据库
lf.client = pymongo.MongoClient(host='localhost', port=27017)
#进⼊wangyi库
lf.db = lf.client.wangyi
def process_item(lf, item, spider):
if dict(item):
#item对象转换成字典,存⼊wangyi库下的xinwen集合
fopenlf.db.xinwen.save(dict(item))return item
def clo_spider(lf,spider):
#断开连接
lf.client.clo()
tting配置
#开启管道
ITEM_PIPELINES = {
'WY.pipelines.WyMongodbPipeline': 300,
}
3)存储在mysql数据库中
import pymysql
class WyMysqlPipeline(object):
conn = None #mysql的连接对象声明
cursor = None#mysql游标对象声明
def open_spider(lf,spider):
print('开始爬⾍')
#链接数据库
< = pymysql.Connect(host='127.0.0.1',port=3306,ur='root',password='123456',db='wangyi')
#编写向数据库中存储数据的相关代码
def process_item(lf, item, spider):
#1.链接数据库
#2.执⾏sql语句
sql = 'inrt into xinwen values("%s","%s")'%(item['genre'],item['url']....)
lf.cursor = lf.conn.cursor()
#执⾏事务
try:
ute(sql)
except Exception as e:
print(e)
return item
def clo_spider(lf,spider):
print('爬⾍结束')
lf.cursor.clo()
tting配置
ITEM_PIPELINES = {
'WY.pipelines.WyMysqlPipeline': 300,
}
4)存储在redis数据库
import redis
class WyRedisPipeline(object):
conn = None
def open_spider(lf,spider):
print('开始爬⾍')
#创建链接对象
< = redis.Redis(host='127.0.0.1',port=6379)
def process_item(lf, item, spider):
dict = {
'genre':item['genre'],
'content':item['content'].......
}
#写⼊redis中
return item
tting配置
ITEM_PIPELINES = {
'WY.pipelines.WyRedisPipeline': 300,
}
可以从上⾯四种存储⽅式看出,模式都是⼀样的,主要是你的类名要和你的tting⾥的要⼀致 5)可以同时存储在多个⾥⾯,以同时存储在⽂件和mongodb中为例
class WyFilePipeline(object):
#构造⽅法
def__init__(lf):
lf.fp = None #定义⼀个⽂件描述符属性
#下列都是在重写⽗类的⽅法:
#开始爬⾍时,执⾏⼀次
def open_spider(lf,spider):
lf.fp = open('./', 'w')
#因为该⽅法会被执⾏调⽤多次,所以⽂件的开启和关闭操作写在了另外两个只会各⾃执⾏⼀次的⽅法中。
def process_item(lf, item, spider):
#将爬⾍程序提交的item进⾏持久化存储
lf.fp.write(item['author'] + ':' + item['content'] + '\n')
return item #为什么要在这返回item,也就是给下⼀种存储⽅法使⽤
#结束爬⾍时,执⾏⼀次
def clo_spider(lf,spider):
lf.fp.clo()
print('爬⾍结束')
import pymongo
class WyMongodbPipeline(object):
def open_spider(lf,spider):
#连接mongodb数据库
lf.client = pymongo.MongoClient(host='localhost', port=27017)
#进⼊wangyi库
lf.db = lf.client.wangyi
def process_item(lf, item, spider):
if dict(item):
#item对象转换成字典,存⼊wangyi库下的xinwen集合
lf.db.xinwen.save(dict(item))
return item
def clo_spider(lf,spider):
#断开连接
lf.client.clo()
tting配置
ITEM_PIPELINES = {
'WY.pipelines.WyFilePipeline': 300,
'WY.pipelines.WyMongodbPipeline': 290,
}
后⾯的数字决定执⾏优先级,
五、UA池和IP代理池
我们都知道哈,我们要爬取⽹页的时候,门户⽹站会有很多反爬策略,⽐如检查UA和IP,为了绕过这层反爬,我们可以使⽤UA池和IP池来解决。改变我们的ua和ip是在发送请求前要做的,⽽且我们要给每个请求都伪装⼀下,所以我可以在中间件的process_request⽅法中添加。利⽤UA池和IP池就会使得每次请求的UA和ip在很⼤程度上不⼀样,就使得被反爬的⼏率变⼩
1,UA池
middlewares.py⽂件中添加⼀个UA类
from scrapy.downloadermiddlewares.uragent import UrAgentMiddleware
import random
class MyUrAgentMiddleWare(UrAgentMiddleware):
def process_request(lf, request, spider):
#这是⼀个可⽤的UA列表
ur_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"
]
#从可⽤UA列表随机取出⼀个UA
ua=random.choice(ur_agent_list)
#封装到请求的headers
request.headers.tdefault('Ur-Agent',ua)
return None
tting配置
DOWNLOADER_MIDDLEWARES = {
'WY.middlewares.WyDownloaderMiddleware': 543,
'WY.middlewares.MyUrAgentMiddleWare': 542,
}
把刚才写的UA中间件添加进去
2,IP代理池
在middlewares.py⽂件中添加⼀个IP类
class MyIPMiddleWare(object):
def process_request(lf, request, spider):
#这是可⽤的ip可以从⽹上的什么快代理、goubanjia等⽹站获取
#这是http请求类型的可⽤IP
PROXY_http = [
'153.180.102.104:80',
'195.208.131.189:56055',
]
#这是https请求类型的可⽤IP
PROXY_https = [