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分析git log日志示例
Feb 27 Python
Python字符串匹配算法KMP实例
Jul 18 Python
python3.4用函数操作mysql5.7数据库
Jun 23 Python
python多维数组切片方法
Apr 13 Python
Python利用公共键如何对字典列表进行排序详解
May 19 Python
Python+OpenCV目标跟踪实现基本的运动检测
Jul 10 Python
python中pip的安装与使用教程
Aug 10 Python
python 通过类中一个方法获取另一个方法变量的实例
Jan 22 Python
一文了解Python并发编程的工程实现方法
May 31 Python
Pycharm创建项目时如何自动添加头部信息
Nov 14 Python
全面介绍python中很常用的单元测试框架unitest
Dec 14 Python
Python中的套接字编程是什么?
Jun 21 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生成月历代码
2007/06/14 PHP
PHP实现获取图片颜色值的方法
2014/07/11 PHP
phpmailer发送邮件之后,返回收件人是否阅读了邮件的方法
2014/07/19 PHP
PHP 在数组中搜索给定的简单实例 array_search 函数
2016/06/13 PHP
全面解析PHP操作Memcache基本函数
2016/07/14 PHP
php rsa 加密,解密,签名,验签详解
2016/12/06 PHP
thinkphp5 migrate数据库迁移工具
2018/02/20 PHP
提高网站信任度的技巧
2008/10/17 Javascript
关于jquery ajax 调用带参数的webservice返回XML数据一个小细节
2012/07/31 Javascript
JAVASCRIPT代码编写俄罗斯方块网页版
2015/11/26 Javascript
利用Js的console对象,在控制台打印调式信息测试Js的实现
2016/11/26 Javascript
Angular下H5上传图片的方法(可多张上传)
2017/01/09 Javascript
jquery Easyui Datagrid实现批量操作(编辑,删除,添加)
2017/02/20 Javascript
JS得到当前时间的方法示例
2017/03/24 Javascript
移动端web滚动分页的实现方法
2017/05/05 Javascript
vue中动态添加class类名的方法
2018/09/05 Javascript
详解vue数组遍历方法forEach和map的原理解析和实际应用
2018/11/15 Javascript
亲自动手实现vue日历控件
2019/06/26 Javascript
node.js Promise对象的使用方法实例分析
2019/12/26 Javascript
vue使用openlayers实现移动点动画
2020/09/24 Javascript
初步理解Python进程的信号通讯
2015/04/09 Python
Django1.7+python 2.78+pycharm配置mysql数据库
2016/10/09 Python
python3.5 email实现发送邮件功能
2018/05/22 Python
Python使用百度翻译开发平台实现英文翻译为中文功能示例
2019/08/08 Python
Python turtle库绘制菱形的3种方式小结
2019/11/23 Python
nginx+uwsgi+django环境搭建的方法步骤
2019/11/25 Python
python GUI库图形界面开发之PyQt5信号与槽基本操作
2020/02/25 Python
美国著名童装品牌:OshKosh B’gosh
2016/08/05 全球购物
在C中是否有模拟继承等面向对象程序设计特性的好方法
2012/05/22 面试题
介绍一下write命令
2014/08/10 面试题
如何撰写岗位职责
2014/02/01 职场文书
弘扬雷锋精神活动演讲稿
2014/03/04 职场文书
现金出纳岗位职责
2014/03/15 职场文书
工作证明英文模板
2014/10/21 职场文书
教你怎么用Python实现多路径迷宫
2021/04/29 Python
能让Python提速超40倍的神器Cython详解
2021/06/24 Python