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 中的多线程 新手必看
Nov 20 Python
python 删除指定时间间隔之前的文件实例
Apr 24 Python
用PyInstaller把Python代码打包成单个独立的exe可执行文件
May 26 Python
Flask框架配置与调试操作示例
Jul 23 Python
基于Django框架利用Ajax实现点赞功能实例代码
Aug 19 Python
利用ImageAI库只需几行python代码实现目标检测
Aug 09 Python
python3实现高效的端口扫描
Aug 31 Python
Python模拟伯努利试验和二项分布代码实例
May 27 Python
Pytorch实现将模型的所有参数的梯度清0
Jun 24 Python
详解Python中的编码问题(encoding与decode、str与bytes)
Sep 30 Python
Python排序函数的使用方法详解
Dec 11 Python
Python3 + Appium + 安卓模拟器实现APP自动化测试并生成测试报告
Jan 27 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新手的一些建议(PHP学习经验总结)
2014/08/20 PHP
Codeigniter(CI)框架分页函数及相关知识
2014/11/03 PHP
PHP实现获取某个月份周次信息的方法
2015/08/11 PHP
Symfony2使用第三方库Upload制作图片上传实例详解
2016/02/04 PHP
100多行PHP代码实现socks5代理服务器[2]
2016/05/05 PHP
PHP chunk_split()函数讲解
2019/02/12 PHP
通过jQuery源码学习javascript(一)
2012/12/27 Javascript
javascript:;与javascript:void(0)使用介绍
2013/06/05 Javascript
屏蔽相应键盘按钮操作
2014/03/10 Javascript
jquery实现多屏多图焦点图切换特效的方法
2015/05/04 Javascript
js实现文字闪烁特效的方法
2015/12/17 Javascript
layui的table单击行勾选checkbox功能方法
2018/08/14 Javascript
详解IOS微信上Vue单页面应用JSSDK签名失败解决方案
2018/11/14 Javascript
微信小程序 腾讯地图SDK 获取当前地址实现解析
2019/08/12 Javascript
Vue filter 过滤器、以及在table中的使用介绍
2020/09/07 Javascript
Vue自定义表单内容检查rules实例
2020/10/30 Javascript
Vue如何实现变量表达式选择器
2021/02/18 Vue.js
Python 文件操作技巧(File operation) 实例代码分析
2008/08/11 Python
Python中几个比较常见的名词解释
2015/07/04 Python
Python生成数字图片代码分享
2017/10/31 Python
python解决pandas处理缺失值为空字符串的问题
2018/04/08 Python
python3 BeautifulSoup模块使用字典的方法抓取a标签内的数据示例
2019/11/28 Python
PyQt5事件处理之定时在控件上显示信息的代码
2020/03/25 Python
Python AutoCAD 系统设置的实现方法
2020/04/01 Python
python右对齐的实例方法
2020/07/05 Python
HTML5之SVG 2D入门3—文本与图像及渲染文本介绍
2013/01/30 HTML / CSS
怎样实现H5+CSS3手指滑动切换图片的示例代码
2019/05/05 HTML / CSS
小学教师学期末自我评价
2013/09/25 职场文书
自我鉴定注意事项
2014/01/19 职场文书
2014社区三八妇女节活动总结
2014/03/01 职场文书
高中语文课后反思
2014/04/27 职场文书
餐饮商业计划书范文
2014/04/29 职场文书
2015年幼儿园中班开学寄语
2015/05/27 职场文书
建国大业观后感600字
2015/06/01 职场文书
导游词之新疆尼雅遗址
2019/10/16 职场文书
css清除浮动clearfix:after的用法详解(附完整代码)
2023/05/21 HTML / CSS