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 相关文章推荐
Python getopt模块处理命令行选项实例
May 13 Python
对dataframe进行列相加,行相加的实例
Jun 08 Python
Python3中内置类型bytes和str用法及byte和string之间各种编码转换 问题
Sep 27 Python
python中使用 xlwt 操作excel的常见方法与问题
Jan 13 Python
spark dataframe 将一列展开,把该列所有值都变成新列的方法
Jan 29 Python
python ddt数据驱动最简实例代码
Feb 22 Python
深入浅析python 协程与go协程的区别
May 09 Python
python调用支付宝支付接口流程
Aug 15 Python
python 实现将小图片放到另一个较大的白色或黑色背景图片中
Dec 12 Python
关于Python解包知识点总结
May 05 Python
python本地文件服务器实例教程
May 02 Python
教你怎么用Python selenium操作浏览器对象的基础API
Jun 23 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
一些php技巧与注意事项分析
2011/02/03 PHP
(PHP实现)只使用++运算实现加法,减法,乘法,除法
2013/06/27 PHP
php修改文件上传限制方法汇总
2015/04/07 PHP
正确的PHP匹配UTF-8中文的正则表达式
2015/05/13 PHP
PHP设计模式之注册树模式分析
2018/01/26 PHP
PHP如何根据文件头检测文件类型实例代码
2018/10/14 PHP
文本框根据输入内容自适应高度的代码
2011/10/24 Javascript
JS脚本defer的作用示例介绍
2014/01/02 Javascript
javascript制作坦克大战全纪录(2)
2014/11/27 Javascript
《JavaScript DOM 编程艺术》读书笔记之JavaScript 简史
2015/01/09 Javascript
js实现兼容IE、Firefox的图片缩放代码
2015/12/08 Javascript
JavaScript的设计模式经典之建造者模式
2016/02/24 Javascript
JS实现探测网站链接的方法【测试可用】
2016/11/08 Javascript
vue2.0中goods选购栏滚动算法的实现代码
2017/05/17 Javascript
angular4实现tab栏切换的方法示例
2017/10/21 Javascript
通过fastclick源码分析彻底解决tap“点透”
2017/12/24 Javascript
一文了解vue-router之hash模式和history模式
2019/05/31 Javascript
js实现橱窗展示效果
2020/01/11 Javascript
浅谈webpack构建工具配置和常用插件总结
2020/05/11 Javascript
[51:20]完美世界DOTA2联赛PWL S2 Magma vs PXG 第一场 11.28
2020/12/01 DOTA
举例讲解Python的lambda语句声明匿名函数的用法
2016/07/01 Python
Python进程间通信之共享内存详解
2017/10/30 Python
python实现石头剪刀布小游戏
2021/01/20 Python
Django 在iframe里跳转顶层url的例子
2019/08/21 Python
FFT快速傅里叶变换的python实现过程解析
2019/10/21 Python
Python线程协作threading.Condition实现过程解析
2020/03/12 Python
css3实现圆锥渐变conic-gradient效果
2020/02/12 HTML / CSS
HTML5中的Article和Section元素认识及使用
2013/03/22 HTML / CSS
温泉秘密:Onsen Secret
2020/07/06 全球购物
俄罗斯苹果优质经销商商店:iPort
2020/05/27 全球购物
法人授权委托书范本
2014/09/17 职场文书
搞笑婚前保证书
2015/02/28 职场文书
好人好事新闻稿
2015/07/17 职场文书
校运会新闻稿
2015/07/17 职场文书
新手开公司创业注意事项有哪些?
2019/07/29 职场文书
应届生个人的求职(自荐信范文2篇)
2019/08/23 职场文书