python使用tornado实现简单爬虫


Posted in Python onJuly 28, 2018

本文实例为大家分享了python使用tornado实现简单爬虫的具体代码,供大家参考,具体内容如下

代码在官方文档的示例代码中有,但是作为一个tornado新手来说阅读起来还是有点困难的,于是我在代码中添加了注释,方便理解,代码如下:

# coding=utf-8
 #!/usr/bin/env python

import time
from datetime import timedelta

try:
  from HTMLParser import HTMLParser
  from urlparse import urljoin, urldefrag
except ImportError:
  from html.parser import HTMLParser
  from urllib.parse import urljoin, urldefrag

from tornado import httpclient, gen, ioloop, queues

 # 设置要爬取的网址
base_url = 'http://www.baidu.com'
 # 设置worker数量
concurrency = 10
 # 此代码会获取base_url下的所有其他url
@gen.coroutine
def get_links_from_url(url):

  try:
    # 通过异步向url发起请求
    response = yield httpclient.AsyncHTTPClient().fetch(url)
    print('fetched %s' % url)
    # 响应如果是字节类型 进行解码
    html = response.body if isinstance(response.body, str) \
      else response.body.decode(errors='ignore')
    # 构建url列表
    urls = [urljoin(url, remove_fragment(new_url))
        for new_url in get_links(html)]
  except Exception as e:
    print('Exception: %s %s' % (e, url))
    # 报错返回空列表
    raise gen.Return([])
  # 返回url列表
  raise gen.Return(urls)


def remove_fragment(url):
  #去除锚点
  pure_url, frag = urldefrag(url)

  return pure_url


def get_links(html):
  #从html页面里提取url
  class URLSeeker(HTMLParser):
    def __init__(self):
      HTMLParser.__init__(self)
      self.urls = []

    def handle_starttag(self, tag, attrs):
      href = dict(attrs).get('href')
      if href and tag == 'a':
        self.urls.append(href)

  url_seeker = URLSeeker()
  url_seeker.feed(html)
  return url_seeker.urls


@gen.coroutine
def main():
  # 创建队列
  q = queues.Queue()
  # 记录开始时间戳
  start = time.time()
  # 构建两个集合
  fetching, fetched = set(), set()

  @gen.coroutine
  def fetch_url():
    # 从队列中取出数据
    current_url = yield q.get()
    try:
      # 如果取出的数据在队列中已经存在 返回
      if current_url in fetching:
        return

      print('fetching %s' % current_url)
      # 如果不存在添加到集合当中
      fetching.add(current_url)
      # 从新放入的链接中继续获取链接
      urls = yield get_links_from_url(current_url)
      # 将已经请求玩的url放入第二个集合
      fetched.add(current_url)

      for new_url in urls:
        # Only follow links beneath the base URL
        # 如果链接是以传入的url开始则放入队列
        if new_url.startswith(base_url):
          yield q.put(new_url)

    finally:
      # 队列内数据减一
      q.task_done()

  @gen.coroutine
  def worker():
    while True:
      # 保证程序持续运行
      yield fetch_url()
  # 将第一个url放入队列
  q.put(base_url)

  # Start workers, then wait for the work queue to be empty.
  for _ in range(concurrency):
    # 启动对应数量的worker
    worker()
  # 等待队列数据处理完成
  yield q.join(timeout=timedelta(seconds=300))
  # 如果两个集合不相等抛出异常
  assert fetching == fetched
  # 打印执行时间
  print('Done in %d seconds, fetched %s URLs.' % (
    time.time() - start, len(fetched)))


if __name__ == '__main__':
  io_loop = ioloop.IOLoop.current()
  io_loop.run_sync(main)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
在Windows服务器下用Apache和mod_wsgi配置Python应用的教程
May 06 Python
详解Django框架中用户的登录和退出的实现
Jul 23 Python
Python彩色化Linux的命令行终端界面的代码实例分享
Jul 02 Python
浅谈python中的变量默认是什么类型
Sep 11 Python
Python实现简单求解给定整数的质因数算法示例
Mar 25 Python
Python实现的简单读写csv文件操作示例
Jul 12 Python
Python 实现中值滤波、均值滤波的方法
Jan 09 Python
Python Django实现layui风格+django分页功能的例子
Aug 29 Python
Python更换pip源方法过程解析
May 19 Python
Python基于httpx模块实现发送请求
Jul 07 Python
Python中qutip用法示例详解
Oct 02 Python
pip install命令安装扩展库整理
Mar 02 Python
python编写简易聊天室实现局域网内聊天功能
Jul 28 #Python
对tensorflow 的模型保存和调用实例讲解
Jul 28 #Python
Python Socket编程之多线程聊天室
Jul 28 #Python
python实现点对点聊天程序
Jul 28 #Python
基于python实现聊天室程序
Jul 27 #Python
Python中return self的用法详解
Jul 27 #Python
TensorFlow打印tensor值的实现方法
Jul 27 #Python
You might like
正则表达式语法
2006/10/09 Javascript
php入门学习知识点七 PHP函数的基本应用
2011/07/14 PHP
Laravel模板引擎Blade中section的一些标签的区别介绍
2015/02/10 PHP
php 问卷调查结果统计
2015/10/08 PHP
教你在header中隐藏php的版本信息
2016/08/10 PHP
php对微信支付回调处理的方法
2018/08/23 PHP
javascript使用eval或者new Function进行语法检查
2010/10/16 Javascript
菜鸟javascript基础资料整理3 正则
2010/12/06 Javascript
JQuery优缺点分析说明
2011/04/10 Javascript
jquery 实现表单验证功能代码(简洁)
2012/07/03 Javascript
jquery中focus()函数实现当对象获得焦点后自动把光标移到内容最后
2013/09/29 Javascript
Jquery和BigFileUpload实现大文件上传及进度条显示
2016/06/27 Javascript
Bootstrap实现带动画过渡的弹出框
2016/08/09 Javascript
vue单页缓存方案分析及实现
2018/09/25 Javascript
vue 使用vue-i18n做全局中英文切换的方法
2018/10/29 Javascript
JS学习笔记之贪吃蛇小游戏demo实例详解
2019/05/29 Javascript
手把手15分钟搭一个企业级脚手架
2019/09/16 Javascript
layui form.render('select', 'test2') 更新渲染的方法
2019/09/27 Javascript
vue vantUI实现文件(图片、文档、视频、音频)上传(多文件)
2019/10/15 Javascript
使用python编写简单的小程序编译成exe跑在win10上
2018/01/15 Python
python实现内存监控系统
2021/03/07 Python
python绘制直线的方法
2018/06/30 Python
10分钟用python搭建一个超好用的CMDB系统
2019/07/17 Python
python爬虫 urllib模块反爬虫机制UA详解
2019/08/20 Python
python logging 重复写日志问题解决办法详解
2020/08/04 Python
Python之多进程与多线程的使用
2021/02/23 Python
佳能英国官方网站:Canon UK
2017/08/08 全球购物
大韩航空官方网站:Korean Air
2017/10/25 全球购物
英国领先的隐形眼镜在线供应商:Lenstore.co.uk
2019/11/24 全球购物
开发中都用到了那些设计模式?用在什么场合?
2014/08/21 面试题
销售主管的自我评价分享
2014/01/03 职场文书
施工班组长岗位职责
2014/01/05 职场文书
就业协议书的作用
2014/04/11 职场文书
销售人才自我评价范文
2014/09/27 职场文书
一次Mysql update sql不当引起的生产故障记录
2022/04/01 MySQL
js判断两个数组相等的5种方法
2022/05/06 Javascript