如何实现通用爬虫并检测可用性?

简介: 我们的目标:根据配置文件信息, 加载爬虫,抓取HTTP代理,进行校验,如果可用,写入到数据库中

一、实现运行爬虫模块
我们的目标:根据配置文件信息, 加载爬虫,抓取HTTP代理,进行校验,如果可用,写入到数据库中
根据以下思路:
1.在run_spider.py中,创建RunSpider类
2.提供一个运行爬虫的run方法,作为运行爬虫的入口,实现核心的处理逻辑
● 根据配置信息,获取爬虫对象列表
● 遍历爬虫对象列表,获取爬虫对象,遍历爬虫对象的get_proxies方法,获取HTTP代理
● 检测HTTP代理(HTTP代理检测模块)
● 如果可用,写入数据库(数据库模块)
● 处理异常,防止一个爬虫内部出错了,影响其他的爬虫

3.使用异步来执行每一个爬虫任务,以提高抓取HTTP代理效率
● 在init方法中创建协程池对象
● 把处理一个代理爬虫的代码抽到一个方法
● 使用异步执行这个方法
● 调用协程的join方法,让当前线程等待队列任务的完成

4.使用schedule模块,实现每隔一定的时间,执行一次爬取任务
● 定义一个start的类方法
● 创建当前类的对象,调用run方法
● 使用schedule模块,每隔一定的时间,执行当前对象的run方法

所以我们可以在run_spider.py中,创建RunSpider类,进而修改settings.py增加HTTP代理爬虫的配置信息。具体代码如下:


from gevent import monkey

monkey.patch_all()
import importlib
from gevent.pool 
import Poolfrom proxy_pool.settings import SPIDER_LIST,RUN_SPIDER_INTERVAL
from proxy_pool.utils.http_validate import check_proxy
from proxy_pool.utils.mongo_pool import MongoPoolfrom proxy_pool.utils.log import logger
import schedule
import time

class RunSpider(object):    
def __init__(self):    
self.mongo_pool = MongoPool()    
self.coroutine_pool = Pool() 

def get_spider_from_settings(self):            
for class_full_name in SPIDER_LIST:           
module_name, class_name = class_full_name.rsplit('.', 1)            
module = importlib.import_module(module_name)            
spider_class = getattr(module, class_name)            
spider = spider_class()            
yield spider

def process_one_spider(self, spider):        
try:            
for proxy in spider.run():            
check_proxy(proxy)            
if proxy.speed != -1:           
self.mongo_pool.insert_one(proxy)            
except Exception as ex:            
logger.warning(ex)

def run(self):       
spider_list = self.get_spider_from_settings()       
for spider in spider_list:        
self.coroutine_pool.apply_async(func=self.process_one_spider, args=(spider,))        
self.coroutine_pool.join()   

@classmethod        
def start(cls):        
rs = cls()        
rs.run()        
schedule.every(RUN_SPIDER_INTERVAL).hours.do(rs.run) 
while True:
schedule.run_pending()
time.sleep(1)

if __name__ == "__main__":    
RunSpider().run()

settings.py代码如下:


 # 配置run_spider模块# 
---配置spider
SPIDER_LIST = {    
"proxy_pool.core.proxy_spider.xila_spider.XiLaSpider",    "proxy_pool.core.proxy_spider.ip3366_spider.Ip3366Spider",}
# ---配置schedule的周期
RUN_SPIDER_INTERVAL = 4

二、实现HTTP代理检测模块
之后,我们需要检查HTTP代理可用性,保证代理池中HTTP代理基本可用。这部分基本是大家耳熟能详的:
1.在proxy_test.py中,创建ProxyTester类

2.提供一个run方法,用于处理检测HTTP代理核心逻辑
我们可以先从数据库中获取所有的HTTP代理,然后从HTTP代理列表中,检查HTTP代理的可用性,如果HTTP代理不可用,让代理分数-1,如果代理分数=0,就从数据库中删除该代理,否则更新该代理,如果代理可用,就恢复该代理的分数,更新到数据库中。

3.为了提高检查的速度,使用异步来执行检测任务
首先,我们需要把要检测的HTTP代理,放到队列中;
其次,把检查一个代理可用性的代码,抽取到一个方法中,从队列中获取HTTP代理,进行检查,检查完毕,调度队列的task_done方法;
然后通过异步回调,使用死循环不断执行这个方法;
最后,开启多个一个异步任务,来处理HTTP代理的检测,可以通过配置文件指定异步数量。

4.使用schedule模块,每隔一定的时间,执行一次检测任务
具体代码如下:


// 
from gevent import monkey
monkey.patch_all()

from gevent.pool import Pool
from queue import Queue
from proxy_pool.utils.mongo_pool import MongoPool
from proxy_pool.settings import ASYNC_COUNT, DEFAULT_SCORE, 
TEST_SPIDER_INTERVAL
from proxy_pool.utils.http_validate import check_proxy
import schedule
import time

class ProxyTest(object):
def __init__(self):
self.mongo_pool = MongoPool()
self.proxy_queue = Queue()
self.coroutine_pool = Pool()

def check_one_proxy(self):
proxy = self.proxy_queue.get()
check_proxy(proxy)
if proxy.speed == -1:
proxy.score -= 1
if proxy.score == 0:
self.mongo_pool.delete_one(proxy)
self.mongo_pool.update_one(proxy)
proxy.score = DEFAULT_SCORE
self.mongo_pool.update_one(proxy)
self.proxy_queue.task_done()

def check_call_back(self, temp):
self.coroutine_pool.apply_async(func=self.check_one_proxy, callback=self.check_call_back)

def run(self):
for proxy in self.mongo_pool.find_all():
self.proxy_queue.put(proxy)
for i in range(ASYNC_COUNT):
self.coroutine_pool.apply_async(func=self.check_one_proxy, callback=
self.check_call_back)self.coroutine_pool.join(
self.proxy_queue.join()
                
@classmethoddef 
start(cls):
rs = cls()
rs.run()
schedule.every(TEST_SPIDER_INTERVAL).hours.do(rs.run)
while True:
schedule.run_pending()
ime.sleep(1)

if __name__ == "__main__":
obj = ProxyTest()
obj.start()
相关文章
|
5月前
|
数据采集 Web App开发 测试技术
如何避免反爬虫程序检测到爬虫行为?
这段内容介绍了几种避免被反爬虫程序检测的方法:通过调整请求频率并遵循网站规则来模拟自然访问;通过设置合理的User-Agent和其他请求头信息来伪装请求;利用代理IP和分布式架构来管理IP地址;以及采用Selenium等工具模拟人类的浏览行为,如随机点击和滚动页面,使爬虫行为更加逼真。这些技巧有助于降低被目标网站识别的风险。
|
5月前
|
数据采集 人工智能 数据可视化
Python selenium爬虫被检测到,该怎么破?
Python selenium爬虫被检测到,该怎么破?
906 8
|
数据采集 Python Web App开发
知乎高颜值图片抓取到本地(Python3 爬虫.人脸检测.颜值检测)
本文代码有参考其他文章 原文链接:https://zhuanlan.zhihu.com/p/34425618
863 0
知乎高颜值图片抓取到本地(Python3 爬虫.人脸检测.颜值检测)
|
数据采集 NoSQL 调度
scrapy框架通用爬虫、深度爬虫、分布式爬虫、分布式深度爬虫,源码解析及应用
scrapy框架是爬虫界最为强大的框架,没有之一,它的强大在于它的高可扩展性和低耦合,使使用者能够轻松的实现更改和补充。 其中内置三种爬虫主程序模板,scrapy.Spider、RedisSpider、CrawlSpider、RedisCrawlSpider(深度分布式爬虫)分别为别为一般爬虫、分布式爬虫、深度爬虫提供内部逻辑;下面将从源码和应用来学习, scrapy.
2670 0
|
数据采集 Python
Scrapy框架--通用爬虫Broad Crawls(上)
通用爬虫(Broad Crawls)介绍 [传送:中文文档介绍],里面除了介绍还有很多配置选项。 通用爬虫一般有以下通用特性: 其爬取大量(一般来说是无限)的网站而不是特定的一些网站。
2226 0
|
数据采集 Python 前端开发
Scrapy笔框架--通用爬虫Broad Crawls(中)
rules = ( Rule(LinkExtractor(allow=r'WebPage/Company.*'),follow=True,callback='parse_company'), Rule(LinkExtractor(allow=r'WebPage/JobDetail.
1294 0
|
数据采集 Python
Scrapy框架--通用爬虫Broad Crawls(下,具体代码实现)
通过前面两章的熟悉,这里开始实现具体的爬虫代码 广西人才网 以广西人才网为例,演示基础爬虫代码实现,逻辑: 配置Rule规则:设置allow的正则-->设置回调函数 通过回调函数获取想要的信息 具体的代码实现: import scrapy from scrapy.
1260 0
|
数据采集 Python 算法
Python爬虫(四)——开封市58同城数据模型训练与检测
前文参考: Python爬虫(一)——开封市58同城租房信息 Python爬虫(二)——对开封市58同城出租房数据进行分析 Python爬虫(三)——对豆瓣图书各模块评论数与评分图形化分析 数据的构建 在这张表中我们可以发现这里有5个数据,这里有两个特征(房租是否少于2000,房屋面积是否大于50)来划分这5个出租房是否租借。
1288 0
|
数据采集 监控 应用服务中间件
[译] 在 Apache 和 Nginx 日志里检测爬虫机器人
本文讲的是[译] 在 Apache 和 Nginx 日志里检测爬虫机器人,现在阻止基于 JavaScript 追踪的浏览器插件享有九位数的用户量,从这一事实可以看出,web 流量日志可以成为一个很好的、能够感知有多少人在访问你的网站的地方。
1864 0
|
2月前
|
数据采集 存储 JSON
Python网络爬虫:Scrapy框架的实战应用与技巧分享
【10月更文挑战第27天】本文介绍了Python网络爬虫Scrapy框架的实战应用与技巧。首先讲解了如何创建Scrapy项目、定义爬虫、处理JSON响应、设置User-Agent和代理,以及存储爬取的数据。通过具体示例,帮助读者掌握Scrapy的核心功能和使用方法,提升数据采集效率。
130 6