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调用windows api锁定计算机示例
Apr 17 Python
python如何实现远程控制电脑(结合微信)
Dec 21 Python
python实现读取并显示图片的两种方法
Jan 13 Python
详解用python实现简单的遗传算法
Jan 02 Python
详解Python自建logging模块
Jan 29 Python
python实现图片九宫格分割
Mar 07 Python
Django的Modelforms用法简介
Jul 27 Python
Python的垃圾回收机制详解
Aug 28 Python
django重新生成数据库中的某张表方法
Aug 28 Python
用什么库写 Python 命令行程序(示例代码详解)
Feb 20 Python
python+Selenium自动化测试——输入,点击操作
Mar 06 Python
Python脚本调试工具安装过程
Jan 11 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
Syphon 秘笈
2021/03/03 冲泡冲煮
让你的网站首页自动选择语言转跳
2006/12/06 PHP
php共享内存段示例分享
2014/01/20 PHP
Javascript 类型转换方法
2010/10/24 Javascript
javascript Array.prototype.slice的使用示例
2013/11/14 Javascript
网页收藏夹显示ICO图标(代码少)
2015/08/04 Javascript
如何利用JS通过身份证号获取当事人的生日、年龄、性别
2016/01/22 Javascript
JavaScript笔记之数据属性和存储器属性
2016/03/31 Javascript
使用jQuery加载html页面到指定的div实现方法
2016/07/13 Javascript
javascript实现无法关闭的弹框
2016/11/27 Javascript
javascript编程开发中取色器及封装$函数用法示例
2017/08/09 Javascript
nodejs实现简单的gulp打包
2017/12/21 NodeJs
微信小程序中实现手指缩放图片的示例代码
2018/03/13 Javascript
webpack4 处理CSS的方法示例
2018/09/03 Javascript
教你如何编写Vue.js的单元测试的方法
2018/10/17 Javascript
详解基于Vue,Nginx的前后端不分离部署教程
2018/12/04 Javascript
mpvue+vant app搭建微信小程序的方法步骤
2019/02/11 Javascript
vue+egg+jwt实现登录验证的示例代码
2019/05/18 Javascript
原生js拖拽功能制作滑动条实例代码
2021/02/05 Javascript
[02:06]DOTA2肉山黑名单魔法终结者 敌法师中文配音鉴赏
2013/06/17 DOTA
python的pdb调试命令的命令整理及实例
2017/07/12 Python
python WindowsError的错误代码详解
2017/07/23 Python
python实现dijkstra最短路由算法
2019/01/17 Python
python发送多人邮件没有展示收件人问题的解决方法
2019/06/21 Python
Python中的pathlib.Path为什么不继承str详解
2019/06/23 Python
NumPy排序的实现
2020/01/21 Python
CSS3 text-shadow实现文字阴影效果
2016/02/24 HTML / CSS
Html5页面获取微信公众号的openid的方法
2020/05/12 HTML / CSS
香港中原电器网上商店:Chung Yuen
2019/06/26 全球购物
手机被没收检讨书
2014/02/22 职场文书
优秀的应届生自荐信
2014/05/23 职场文书
婚前财产协议书范本
2014/10/19 职场文书
国庆庆典邀请函
2015/02/02 职场文书
幼儿园老师个人总结
2015/02/28 职场文书
2016元旦晚会主持词开场白和结束语
2015/12/04 职场文书
Python+Matplotlib+LaTeX玩转数学公式
2022/02/24 Python