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 yield 小结和实例
Apr 25 Python
Python文件夹与文件的相关操作(推荐)
Jul 25 Python
django之session与分页(实例讲解)
Nov 13 Python
python实现员工管理系统
Jan 11 Python
Python3.5 创建文件的简单实例
Apr 26 Python
python绘制直线的方法
Jun 30 Python
利用python在excel里面直接使用sql函数的方法
Feb 08 Python
Python循环结构的应用场景详解
Jul 11 Python
Python操作SQLite/MySQL/LMDB数据库的方法
Nov 07 Python
python tornado修改log输出方式
Nov 18 Python
python向图片里添加文字
Nov 26 Python
keras 自定义loss层+接受输入实例
Jun 28 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
深入密码加salt原理的分析
2013/06/06 PHP
php实现高效获取图片尺寸的方法
2014/12/12 PHP
WordPress中用于获取及自定义头像图片的PHP脚本详解
2015/12/17 PHP
使用phpexcel类实现excel导入mysql数据库功能(实例代码)
2016/05/12 PHP
PHP mysqli_free_result()与mysqli_fetch_array()函数详解
2016/09/21 PHP
thinkPHP js文件中U方法不被解析问题的解决方法
2016/12/05 PHP
使用php完成常见的文件上传功能(推荐)
2017/01/13 PHP
js捕获鼠标右键菜单中的粘帖事件实现代码
2013/04/01 Javascript
JS图片切换的具体方法(带缩略图版)
2013/11/12 Javascript
jQuery判断复选框是否勾选的原理及示例
2014/05/21 Javascript
理解JavaScript的变量的入门教程
2015/07/07 Javascript
三种带箭头提示框总结实例
2016/06/14 Javascript
一个简单的JavaScript Map实例(分享)
2016/08/03 Javascript
VueJS 集成 Medium Editor的示例代码 (自定义编辑器按钮)
2017/08/24 Javascript
关于 angularJS的一些用法
2017/11/29 Javascript
JavaScript实现的简单Tab点击切换功能示例
2018/07/06 Javascript
原生javascript实现连连看游戏
2019/01/03 Javascript
微信小程序MUI侧滑导航菜单示例(Popup弹出式,左侧不动,右侧滑动)
2019/01/23 Javascript
详解Vue中组件传值的多重实现方式
2019/08/16 Javascript
python opencv之SIFT算法示例
2018/02/24 Python
Python(TensorFlow框架)实现手写数字识别系统的方法
2018/05/29 Python
Python多项式回归的实现方法
2019/03/11 Python
对Python中TKinter模块中的Label组件实例详解
2019/06/14 Python
python3连接kafka模块pykafka生产者简单封装代码
2019/12/23 Python
通过python调用adb命令对App进行性能测试方式
2020/04/23 Python
使用Keras 实现查看model weights .h5 文件的内容
2020/06/09 Python
python 最简单的实现适配器设计模式的示例
2020/06/30 Python
一级方程式赛车官方网上商店:F1 Store(支持中文)
2018/01/12 全球购物
台湾最大银发乐活百货:乐龄网
2018/05/21 全球购物
Stuarts London美国/加拿大:世界领先的独立男装零售商之一
2019/03/18 全球购物
新加坡领先的在线生活方式和杂货购物网站:EAMART
2019/04/02 全球购物
地球鞋加拿大官网:Earth Shoes Canada
2020/11/17 全球购物
Ruby中的保护方法和私有方法与一般面向对象程序设计语言的一样吗
2013/05/01 面试题
井冈山红色之旅感想
2014/10/07 职场文书
Python预测分词的实现
2021/06/18 Python
Python获取指定日期是"星期几"的6种方法
2022/03/13 Python