赞
踩
行吧,咱们聊聊。你看,现在大家都在讲这个异步、多线程,挺火的。然后就有人开始拿来跟Scrapy比,说得好像Scrapy已经过时了似的。其实不是那么回事儿,你要是只想快速搭个接口什么的,那确实,用不着Scrapy。可要是想搞个大动作,像分布式这种大架构,那Scrapy简直就是救星,能省你不少事儿。
就好比组装电脑,有些哥们儿就是喜欢自己选配件,一手搭起来,那感觉确实爽。但Scrapy啊,它就像是那个成熟的电脑品牌,一直更新迭代,背后还有一大帮人支持。你买个成套的就完事了,啥都有了,多省心!
接着,得聊一聊,Scrapy这异步是怎么回事。它用的框架叫Twisted,老牌框架了,可不是现在流行的asyncio。asyncio那是后来Python 3.4引入的。用了Twisted的Scrapy,做大规模并发请求,效率那叫一个快。再加上它弄得那些下载器中间件、爬虫中间件、管道啥的,搞开发用起来就是顺手。
分布式嘛,Scrapy用的是Scrapy-Redis,串起来也挺轻松。让你的爬虫能在多台机器上干活,效率那叫一个杠,数据处理能力直接upup。这就是为啥如果你要搞点大动静,我肯定推Scrapy,靠谱!
但如果你想体验一下aiohttp在Scrapy里的感觉,那可得自己动手了。就是得弄个适配器之类的整合进去。比如写个中间件,用aiohttp代替Scrapy原生的下载器来发HTTP请求。这么干可能能用到aiohttp的一些独门秘技,但要是碰上问题,那得自己一个个查,Scrapy那边的,aiohttp这边的,都得弄。
所以呢,直白点说,咱直接用Scrapy就挺好。不麻烦,效率又高,特别是团队项目,简直完美。Scrapy的文档超全,社区也挺活跃,啥问题一查基本都能解决。
当然了,如果你就喜欢折腾,想亲手搞一搞,也行啊。技术圈子里自己动手那点乐趣儿是真实的。但是啊,别忘了,时间就是金钱,能用成熟的框架就别自己搞了,早点儿出成果才是王道。大项目上手了你就知道,这省力的意义有多大了。
那么怎么进行转换呢?
对标案例,可以看我之前写的:
根据提供的`IpPoolPipeline`,将Scrapy框架中的其他部分配合起来以实现完整的代理IP爬取和验证功能,以下是可能需要配合的几个主要部分:
- 在`items.py`中定义一个`ProxyItem`类,例子如下:
-
- ```python
- # myproject/items.py
- import scrapy
-
- class ProxyItem(scrapy.Item):
- ip = scrapy.Field()
- port = scrapy.Field()
- # myproject/spiders/ippool_spider.py
- import scrapy
- from myproject.items import ProxyItem
-
- class IppoolSpider(scrapy.Spider):
- name = 'ippool'
- allowed_domains = ['example.com'] # 这里填写你将要爬取代理信息的网站域名
- start_urls = ['http://www.example.com/proxies']
-
- def parse(self, response):
- # 网页解析逻辑...
- for row in response.css('table tr'):
- item = ProxyItem()
- item['ip'] = row.xpath('./td[1]/text()').get()
- item['port'] = row.xpath('./td[2]/text()').get()
- yield item
- # myproject/middlewares.py
- import random
-
- class ProxyMiddleware(object):
- def process_request(self, request, spider):
- request.meta['proxy'] = 'http://some_proxy_server:port'
- # 或者使用随机代理:
- # request.meta['proxy'] = random.choice(PROXY_POOL)
- # myproject/settings.py
-
- ITEM_PIPELINES = {
- 'myproject.pipelines.IpPoolPipeline': 300,
- # ...
- }
-
- DOWNLOADER_MIDDLEWARES = {
- 'myproject.middlewares.ProxyMiddleware': 400,}
- import scrapy
- from scrapy.exceptions import DropItem
- from scrapy.utils.project import get_project_settings
- import redis
-
- class IpPoolPipeline:
- def __init__(self, crawler):
- self.crawler = crawler
- self.settings = get_project_settings()
- self.redis_conn = redis.StrictRedis(
- host=self.settings.get('REDIS_HOST'),
- port=self.settings.get('REDIS_PORT'),
- db=self.settings.get('REDIS_DB')
- )
-
- @classmethod
- def from_crawler(cls, crawler):
- return cls(crawler)
-
- def process_item(self, item, spider):
- # 发起一个通过代理发起请求,以验证代理是否有效
- proxy = f"http://{item['ip']}:{item['port']}"
- meta = {'proxy': proxy, 'item': item, 'dont_retry': True, 'download_timeout': 10}
- return scrapy.Request(url="http://httpbin.org/ip", callback=self.validate_ip, meta=meta, dont_filter=True, errback=self.ignore_failure)
-
- def validate_ip(self, response):
- item = response.meta['item']
-
- # 如果代理可用,并且代理的IP出现在了我们的响应中,说明这个代理是有效的
- proxy_ip = item['ip']
- if proxy_ip in response.text:
- # 验证成功后将item存入Redis
- self.store_in_redis(item)
- else:
- # 如果验证不通过,直接抛出DropItem异常,item不会被进一步处理
- raise DropItem(f"无效的代理被忽略: {item['ip']}:{item['port']}")
-
- def ignore_failure(self, failure):
- item = failure.request.meta['item']
- # 只打印消息而不做进一步处理
- print(f"代理验证失败:{item['ip']}:{item['port']}")
-
- def store_in_redis(self, item):
- # 使用集合sadd来存储有效的IP,避免重复
- self.redis_conn.sadd('valid_ip', f"{item['ip']}:{item['port']}")
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。