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写的图片蜘蛛人代码
Aug 27 Python
python实现批量改文件名称的方法
May 25 Python
Python基于checksum计算文件是否相同的方法
Jul 09 Python
NetworkX之Prim算法(实例讲解)
Dec 22 Python
Python基于OpenCV实现视频的人脸检测
Jan 23 Python
Python中函数参数调用方式分析
Aug 09 Python
python找出完数的方法
Nov 12 Python
Python实现剪刀石头布小游戏(与电脑对战)
Dec 31 Python
SpringBoot实现登录注册常见问题解决方案
Mar 04 Python
探秘TensorFlow 和 NumPy 的 Broadcasting 机制
Mar 13 Python
基于K.image_data_format() == 'channels_first' 的理解
Jun 29 Python
python 日志模块logging的使用场景及示例
Jan 04 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通过curl模拟登陆DZ论坛
2015/05/11 PHP
PHP表单提交后引号前自动加反斜杠的原因及三种办法关闭php魔术引号
2015/09/30 PHP
PHP 读取大文件并显示的简单实例(推荐)
2016/08/12 PHP
php array_map使用自定义的函数处理数组中的每个值
2016/10/26 PHP
PHP多种序列化/反序列化的方法详解
2017/06/23 PHP
Laravel框架Blade模板简介及模板继承用法分析
2019/12/03 PHP
PHP的图像处理实例小结【文字水印、图片水印、压缩图像等】
2019/12/20 PHP
php 函数中静态变量使用的问题实例分析
2020/03/05 PHP
jQuery使用一个按钮控制图片的伸缩实现思路
2013/04/19 Javascript
js取消单选按钮选中并判断对象是否为空
2013/11/14 Javascript
深入理解JavaScript系列(17):面向对象编程之概论详细介绍
2015/03/04 Javascript
javascript每日必学之条件分支
2016/02/17 Javascript
JavaScript中文件上传API详解
2016/04/01 Javascript
JavaScript知识点总结(十)之this关键字
2016/05/31 Javascript
基于jQuery ligerUI实现分页样式
2016/09/18 Javascript
BootStrap与Select2使用小结
2017/02/17 Javascript
package.json文件配置详解
2017/06/15 Javascript
详解jQuery同步Ajax带来的UI线程阻塞问题及解决办法
2017/08/09 jQuery
使用javaScript实现鼠标拖拽事件
2020/04/03 Javascript
node文件批量重命名的方法示例
2017/10/23 Javascript
详解node.js中的npm和webpack配置方法
2018/01/21 Javascript
vue 自定义指令自动获取文本框焦点的方法
2018/08/25 Javascript
vue实现div可拖动位置也可改变盒子大小的原理
2020/09/16 Javascript
vue穿梭框实现上下移动
2021/01/29 Vue.js
python threading模块操作多线程介绍
2015/04/08 Python
python类装饰器用法实例
2015/06/04 Python
python去除文件中空格、Tab及回车的方法
2016/04/12 Python
python 实时得到cpu和内存的使用情况方法
2018/06/11 Python
对Python中for复合语句的使用示例讲解
2018/11/01 Python
Python如何优雅获取本机IP方法
2019/11/10 Python
Python包,__init__.py功能与用法分析
2020/01/07 Python
CSS3——齿轮转动关键代码
2013/05/02 HTML / CSS
银行求职信个人范文
2013/12/16 职场文书
会计系中文个人求职信
2013/12/24 职场文书
民事诉讼答辩状范文
2015/05/21 职场文书
维护民族团结心得体会2016
2016/01/15 职场文书