import asyncio
import aiohttp
import async_timeout
from lxml import html
from timeit import default_timer as timer from db import DBData class Crawler:
def __init__(self, **kwargs):
self.domains = kwargs["domains"]
self.max_depth = kwargs["max_depth"]
self.max_retries = 3
self.max_workers = 10
self.Q = asyncio.Queue()
self.db_Q = asyncio.Queue()
self.cache = set()
self.count = 0
self.loop = asyncio.get_event_loop()
self.db_data = DBData() # Clear
self.db_data.clear_crawler() async def get(self, url, timeout):
with async_timeout.timeout(timeout):
async with self.session.get(url) as response:
return await response.text() async def extract_urls(self, url, timeout=10):
tree = html.fromstring(await self.get(url, timeout))
# Search only in domains
return {p for p in tree.xpath("//a/@href")}
# if any(domain in p for domain in self.domains)} async def worker(self):
while True:
url, depth, retries = await self.Q.get()
if url in self.cache:
self.db_Q.put_nowait(url)
self.Q.task_done()
continue
try:
new_urls = await self.extract_urls(url)
except Exception as e:
if retries <= self.max_retries:
self.Q.put_nowait((url, depth, retries + 1))
else:
print("Error in %s: %s" % (url, repr(e)))
else:
self.cache.add(url)
self.count += 1
self.db_Q.put_nowait(url)
print("Depth: %s Retry: %s Visited: %s" % (depth, retries, url))
if depth+1 <= self.max_depth:
for x in new_urls:
self.Q.put_nowait((x, depth + 1, retries))
self.Q.task_done() async def run(self):
async with aiohttp.ClientSession(loop=self.loop) as session:
self.session = session
workers = [self.worker() for _ in range(self.max_workers)]
workers += [self.write_to_db() for _ in range(self.max_workers)]
tasks = [self.loop.create_task(x) for x in workers]
await asyncio.sleep(5)
await self.Q.join()
await self.db_Q.join()
for task in tasks:
task.cancel() def start(self):
for domain in self.domains:
print("Crawling %s start..." % domain) self.Q.put_nowait((domain, 0, 0))
start_time = timer()
self.loop.run_until_complete(asyncio.gather(self.run()))
self.loop.close()
runtime = timer() - start_time print("Crawling %s end. Exec time: %s. Requests: %s" % (
domain, runtime, self.count)) async def write_to_db(self):
while True:
address = await self.db_Q.get()
if await self.db_data.check_url(address) is None:
self.db_data.add_url(address)
print("Write to DB: %s" % address)
self.db_Q.task_done() if __name__ == "__main__":
options = {
"domains": ["https://www.yahoo.com/news/"],
"max_depth": 1
}
c = Crawler(**options)
c.start()

aiohttp爬虫的模板,类的形式的更多相关文章

  1. C++模板类的使用

    1.定义模板类 通过类似于下面的语法可以定义一个模板类: template<typename T> class Job : public virtual RefBase { public: ...

  2. C++:类模板与模板类

    6.3 类模板和模板类 所谓类模板,实际上是建立一个通用类,其数据成员.成员函数的返回值类型和形参类型不具体指定,用一个虚拟的类型来代表.使用类模板定义对象时,系统会实参的类型来取代类模板中虚拟类型从 ...

  3. C++ 模板类解析

    具体模板类作用这边就不细说了,下面主要是描述下模板类的使用方法以及注意的一些东西. #include <iostream> using namespace std; template &l ...

  4. 使用模板类导致error LNK2019: 无法解析的外部符号

    原地址 1.定义模板类: template<class T> class Stack {....}; 2.定义模板成员函数: 每个函数头都要以相同的模板声明打头,并将类限定符改成:类名&l ...

  5. 开涛spring3(7.2) - 对JDBC的支持 之 7.2 JDBC模板类

    7.2  JDBC模板类 7.2.1  概述 Spring JDBC抽象框架core包提供了JDBC模板类,其中JdbcTemplate是core包的核心类,所以其他模板类都是基于它封装完成的,JDB ...

  6. 7.2 C++模板类实例化

    参考:http://www.weixueyuan.net/view/6399.html 总结: array < int >表明用int类型来代替模板类中的类参数“T”,编译器会将模板类ar ...

  7. [C++]模板类和模板函数

    参考: C++ 中模板使用详解 C++模板详解 概念 为了避免因重载函数定义不全面而带来的调用错误,引入了模板机制 定义 模板是C++支持参数化多态的工具,使用模板可以使用户为类或者函数声明一种一般模 ...

  8. (转)JDBC模板类。

    Spring JDBC抽象框架core包提供了JDBC模板类,其中JdbcTemplate是core包的核心类,所以其他模板类都是基于它封装完成的,JDBC模板类是第一种工作模式. JdbcTempl ...

  9. spring3:对JDBC的支持 之 JDBC模板类

    7.2  JDBC模板类 7.2.1  概述 Spring JDBC抽象框架core包提供了JDBC模板类,其中JdbcTemplate是core包的核心类,所以其他模板类都是基于它封装完成的,JDB ...

随机推荐

  1. Excel VBA Range对象基本操作应用示例

    [示例01] 赋值给某单元格[示例01-01] Sub test1()Worksheets("Sheet1").Range("A5").Value = 22Ms ...

  2. c#微信开发,使用JS-SDK自定义分享功能,分享朋友圈,分享给朋友等

    如果一个后端开发掌握了微信开发,甚至有微信开发上线项目,这在换工作的时候 还是有竞争力的. 微信开发的资料很多,但是用asp.net c#进行微信开发好像比较少,或者资料不够完整. 使用JS-SDK自 ...

  3. Linux入门-4 Linux下获取帮助

    help MAN INFO doc help <command> -h或<command> --help whatis <cmd> MAN man <comm ...

  4. 微信小程序及各种平台对接常用可逆加密算法aes256

    不同程序之间经常会交换数据,我们经常采用的套路是: 假设要传输的信息是json,我们假设其为json_data,通过http传递信息为 json_data_encode=json_data&s ...

  5. scala流程控制语句以及方法和函数

    1.if else表达式 scala中没有三目运算符,因为根本不需要.scala中if else表达式是有返回值的,如果if或者else返回的类型不一样,就返回Any类型(所有类型的公共超类型). 例 ...

  6. markdown编辑器安装

    打算使用MarkDown了,打算整理自己的知识了. 多年以前,喜欢将自己看到好东西,转载在博客.或者将遇到过的问题以及解决方案,记录在博客.06毕业后为了生活折腾,Tom网上的博客无暇东顾,等稳定闲下 ...

  7. Java虚拟机14:类加载器

    类与类加载器 虚拟机设计团队把类加载阶段张的"通过一个类的全限定名来获取此类的二进制字节流"这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类.实现这 ...

  8. 贪心——HDU-5969 最大的位或

    HDU-5969:http://acm.hdu.edu.cn/showproblem.php?pid=5969 一开始也是分了类,觉得要两种情况,l 与 r 位数相同与不同的情况,仔细想一下,可以一起 ...

  9. 9、Web Service-IDEA-jaxrs 服务端客户端的实现

    关于RestFul编程可以参考:https://www.cnblogs.com/wang-yaz/p/9237981.html 关于jaxrs的实现需要有restful的理解. 话不多说直接上代码!! ...

  10. 6、Web Service-拦截器

    1.为什么CXF设置拦截器 为了在webservice请求过程中,能动态操作请求和响应数据, CXF设计了拦截器.拦截器分类 1.按所处的位置分:服务器端拦截器,客户端拦截器 2.按消息的方向分:入拦 ...