本文来自网易云社区

作者:王涛

本文大纲:

  • 简易介绍今天要讲解的两个爬虫开发的python库

  • 详细介绍 requests库及函数中的各个参数

  • 详细介绍 tornado 中的httpcilent的应用

  • 总结

目标:了解python中常用的快速开发爬虫的工具包。

基础:    python的基础语法(2.7)

Here we go!

简易爬虫:我把一次性代码称为简易爬虫,这些爬虫是定制化的,不能通用。不像爬虫框架,通过配置就可以实现一个新的抓取需求。对于入门的盆友来讲,本篇文章基本可以满足你的需求。如果有对框架感兴趣的盆友,了解了本文的tornado,对于你了解pyspider这个框架也是有好处的。(Pyspdier使用了tornado框架)

一、简介requests与tornado

随着大数据、人工智能、机器学习的发展,python语言的编程地位保持着持续提升。其它方面的功能暂且不表(因为我不知道),我们来谈谈python在爬虫方面的表现。

1、requests 基础

相信想快速上手爬虫的人都会选择python,并且选择requests库,请问获取百度首页源码要几步?
答:三步
第一步:下载和安装python
第二步:pip 安装 requests库
第三步:执行 python -c 'import requests; print requests.get("http://www.baidu.com").content'

  1. python -'import requests; print requests.get("http://www.baidu.com").content'<!DOCTYPE html>
  2. <!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div <div <div <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span ><input id=kw name=wd value maxlength=255 autocomplete=off autofocus></span><span ><input type=submit id=su value=百度一下 ></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews <a href=http://www.hao123.com name=tj_trhao123 <a href=http://map.baidu.com name=tj_trmap <a href=http://v.baidu.com name=tj_trvideo <a href=http://tieba.baidu.com name=tj_trtieba <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login </noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" >登录</a>');</script> <a href=//www.baidu.com/more/ name=tj_briicon style="display: block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>关于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>&copy;2017 Baidu <a href=http://www.baidu.com/duty/>使用百度前必读</a>  <a href=http://jianyi.baidu.com/ <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>
2、requests高效抓取

高效抓取,那我们把串行改成并行。一谈并发,大家就想到多线程,多进程。

但是大家知道,由于Ptyhon的解释器在执行的时候用了一把大锁GIL保证解释器(或者是python vm)在解释执行的时候只有一个线程得到调度,所以CPython事实上是伪多线程的,也就是本质上还是单线程。 注: GIL存在于CPython中,Jython没有这个限制(http://www.jython.org/jythonbook/en/1.0/Concurrency.html)

为了程序简单,就直接多线程运行了,毕竟Python自带的大多数数据结构是线程安全的(list,dict,tuple等),你可以不用考虑竞争给代码带来的复杂性。

协程这个概念在很多编程语言中都已经支持了。python中通过yield关键字来实现协程,今天再给大家介绍一款基于协程的异步非阻塞框架 tornado. 使用它来实现网络请求,相比于多线程的requests更高效。

3、tornado简介

在介绍tornado之前,我们简单介绍一下协程的概念。

3.1 协程

在单线程的前提条件下:
面向过程的编程中,我们会把一些代码块封装成一个函数,这个函数的特点:一个入口,一个出口.当我们调用一个函数时,会等它结束了才能继续执行后续的代码。 而协程在单线程的条件下,一个函数可以多次进入,多次返回,我们在调用协程函数的时候,可以在它的中断点暂时返回去执行其它的协程函数。(这有点像多线程,某一线程阻塞,CPU会调度其它线程)。

下面给一段代码看一下运行效果,逻辑很简单,我们把show_my_sleep向IOLoop中添加了四次,每次入参不同。 show_my_sleep中打印信息,休眠,打印信息。根据结果,我们可以看到show_my_sleep函数在yield 语句进入休眠,暂时交出了运行权,等休眠结束后,从yield语句后开始继续执行。

  1. import randomfrom tornado.ioloop import IOLoopfrom tornado import gen@gen.coroutinedef show_my_sleep(idx):
  2.     interval = random.uniform(5,20)    print "[{}] is going to sleep {} seconds!".format(idx, interval)    yield gen.sleep(interval)    # 此处会作为中断点,交出代码运行权
  3.     print "[{}] wake up!!".format(idx)def main():
  4.     io_loop = IOLoop.current()
  5.     io_loop.spawn_callback(show_my_sleep, 1)  # 下一次循环的时候调度这个函数
  6.     io_loop.spawn_callback(show_my_sleep, 2)
  7.     io_loop.spawn_callback(show_my_sleep, 3)
  8.     io_loop.spawn_callback(show_my_sleep, 4)
  9.     io_loop.start()if __name__ == "__main__":
  10.     main()

结果:

  1. [1] is going to sleep 5.19272014406 seconds![2] is going to sleep 9.42334286914 seconds![3] is going to sleep 5.11032311172 seconds![4] is going to sleep 13.0816614451 seconds![3] wake up!![1] wake up!![2] wake up!![4] wake up!!
3.2 Tornado 简介

[译:https://www.tornadoweb.org/en/stable/guide/intro.html]

  1. Tornado 是基于Python实现的异步网络框架,它采用非阻塞IO,可以支持成千上万的并发访问量,
  2. 所以非常适合于长轮询和Websocket 以及其它需要持久连接的应用场景。Tornado 主要包含四个部分:- web框架,包括了RequestHandler(它可以用来创建WEB应用和各种支持的类)- 客户端、服务端侧的HTTP实现(包括HttpServer AsyncHttpClient)- 包含了 IOLoopIOStream 的异步网络库,它们作为HTTP组件的内置块并且可以用来实现其它协议。- 协程库(tornado.gen),它使异步代码写起来比链式回调更直接。Tornado WEB框架和HTTP server 在一起可以作为WSGI的全栈替代。
  3. WSGI容器里可以使用Tornado web框架,也可以用Http server 作为其它WSGI框架的容器,不过任意一种组合都是有缺陷的。
  4. 为了充分发挥tornado的优势 ,你需要使用tornado web框架和http server.

我们在这里主要借用tornado的 httpclient和协程库,来实现单线程下并发网络请求。
Here, show you the code!

  1. import tracebackfrom tornado.ioloop import IOLoopfrom tornado import genfrom tornado.curl_httpclient import CurlAsyncHTTPClientfrom tornado.httpclient import HTTPRequest@gen.coroutinedef fetch_url(url):
  2.     """抓取url"""
  3.     try:
  4.         c = CurlAsyncHTTPClient()  # 定义一个httpclient
  5.         req = HTTPRequest(url=url)  # 定义一个请求
  6.         response = yield c.fetch(req)  # 发起请求
  7.         print response.body
  8.         IOLoop.current().stop()  # 停止ioloop线程
  9.     except:        print traceback.format_exc()def main():
  10.     io_loop = IOLoop.current()
  11.     io_loop.spawn_callback(fetch_url, "http://www.baidu.com")  # 添加协程函数到Ioloop循环中
  12.     io_loop.start()if __name__ == "__main__":
  13.     main()
4、tornado并发

这里简单讲,就是通过向ioloop中添加回调,来实现多个回调的并行调用。

  1. def main():
  2.     io_loop = IOLoop.current()
  3.     io_loop.spawn_callback(fetch_url, "http://www.baidu.com")  # 下一次循环的时候调度这个函数
  4.     '''
  5.     io_loop.spawn_callback(fetch_url, url1)  
  6.     ... ...
  7.     io_loop.spawn_callback(fetch_url, urln) 
  8.     '''
  9.     io_loop.start()if __name__ == "__main__":
  10.     main()

简单介绍过两个应用包后,来详细介绍一下关键函数及参数。

二、requests 关键函数及参数

我们利用requests开发爬虫时,主要会用到 get,post 方法,另外,为了应对反爬虫策略,会添加一些自定义的http头信息,我们从这个应用角度介绍一下requests的两个关键函数get和post。
函数定义:

  1. def get(url, params=None, **kwargs):
  2.     """Sends a GET request.
  3.  
  4.     :param url: URL for the new :class:`Request` object.
  5.     :param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`.
  6.     :param \*\*kwargs: Optional arguments that ``request`` takes.
  7.     :return: :class:`Response <Response>` object
  8.     :rtype: requests.Response
  9.     """
  10.  
  11.     kwargs.setdefault('allow_redirects', True)    return request('get', url, params=params, **kwargs)
  1. def post(url, data=None, json=None, **kwargs):
  2.     """Sends a POST request.
  3.  
  4.     :param url: URL for the new :class:`Request` object.
  5.     :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`.
  6.     :param json: (optional) json data to send in the body of the :class:`Request`.
  7.     :param \*\*kwargs: Optional arguments that ``request`` takes.
  8.     :return: :class:`Response <Response>` object
  9.     :rtype: requests.Response
  10.     """
  11.  
  12.     return request('post', url, data=data, json=json, **kwargs)

我们可以看到,requests的get,post方法都会 调用 request函数,request函数定义如下:

  1.     def request(self, method, url,        params=None,
  2.         data=None,
  3.         headers=None,
  4.         cookies=None,
  5.         files=None,
  6.         auth=None,
  7.         timeout=None,
  8.         allow_redirects=True,
  9.         proxies=None,
  10.         hooks=None,
  11.         stream=None,
  12.         verify=None,
  13.         cert=None,
  14.         json=None):
  15.         """Constructs a :class:`Request <Request>`, prepares it and sends it.
  16.         Returns :class:`Response <Response>` object.
  17.  
  18.         :param method: method for the new :class:`Request` object.
  19.         :param url: URL for the new :class:`Request` object.
  20.         :param params: (optional) Dictionary or bytes to be sent in the query          
  21.           string for the :class:`Request`.
  22.         :param data: (optional) Dictionary, bytes, or file-like object to send         
  23.            in the body of the :class:`Request`.
  24.         :param json: (optional) json to send in the body of the
  25.             :class:`Request`.
  26.         :param headers: (optional) Dictionary of HTTP Headers to send with the
  27.             :class:`Request`.
  28.         :param cookies: (optional) Dict or CookieJar object to send with the
  29.             :class:`Request`.
  30.         :param files: (optional) Dictionary of ``'filename': file-like-objects``         
  31.            for multipart encoding upload.
  32.         :param auth: (optional) Auth tuple or callable to enable
  33.             Basic/Digest/Custom HTTP Auth.
  34.         :param timeout: (optional) How long to wait for the server to send
  35.             data before giving up, as a float, or a :ref:`(connect timeout,
  36.             read timeout) <timeouts>` tuple.
  37.         :type timeout: float or tuple
  38.         :param allow_redirects: (optional) Set to True by default.
  39.         :type allow_redirects: bool
  40.         :param proxies: (optional) Dictionary mapping protocol or protocol and
  41.             hostname to the URL of the proxy.
  42.         :param stream: (optional) whether to immediately download the response
  43.             content. Defaults to ``False``.
  44.         :param verify: (optional) whether the SSL cert will be verified.
  45.             A CA_BUNDLE path can also be provided. Defaults to ``True``.
  46.         :param cert: (optional) if String, path to ssl client cert file (.pem).
  47.             If Tuple, ('cert', 'key') pair.
  48.         :rtype: requests.Response
  49.         """

网易云免费体验馆,0成本体验20+款云产品!

更多网易研发、产品、运营经验分享请访问网易云社区

相关文章:
【推荐】 网易美学-系统架构系列1-分布式与服务化
【推荐】 Hi,这有一份风控体系建设干货

爬虫开发python工具包介绍 (1)的更多相关文章

  1. 爬虫开发python工具包介绍 (2)

    本文来自网易云社区 作者:王涛 可选参数我们一一介绍一下: 参数 释义 示例 params 生成url中?号后面的查询Key=value 示例1: >>>payload = {'ke ...

  2. 爬虫开发python工具包介绍 (4)

    本文来自网易云社区 作者:王涛 此处我们给出几个常用的代码例子,包括get,post(json,表单),带证书访问:Get 请求 @gen.coroutine def fetch_url():     ...

  3. 爬虫开发python工具包介绍 (3)

    本文来自网易云社区 作者:王涛         :arg str url: URL to fetch         :arg str method: HTTP method, e.g. " ...

  4. Python爬虫开发与项目实战

    Python爬虫开发与项目实战(高清版)PDF 百度网盘 链接:https://pan.baidu.com/s/1MFexF6S4No_FtC5U2GCKqQ 提取码:gtz1 复制这段内容后打开百度 ...

  5. Python 3网络爬虫开发实战》中文PDF+源代码+书籍软件包

    Python 3网络爬虫开发实战>中文PDF+源代码+书籍软件包 下载:正在上传请稍后... 本书书籍软件包为本人原创,在这个时间就是金钱的时代,有些软件下起来是很麻烦的,真的可以为你们节省很多 ...

  6. Python 3网络爬虫开发实战中文 书籍软件包(原创)

    Python 3网络爬虫开发实战中文 书籍软件包(原创) 本书书籍软件包为本人原创,想学爬虫的朋友你们的福利来了.软件包包含了该书籍所需的所有软件. 因为软件导致这个文件比较大,所以百度网盘没有加速的 ...

  7. Python 3网络爬虫开发实战中文PDF+源代码+书籍软件包(免费赠送)+崔庆才

    Python 3网络爬虫开发实战中文PDF+源代码+书籍软件包+崔庆才 下载: 链接:https://pan.baidu.com/s/1H-VrvrT7wE9-CW2Dy2p0qA 提取码:35go ...

  8. 《Python 3网络爬虫开发实战中文》超清PDF+源代码+书籍软件包

    <Python 3网络爬虫开发实战中文>PDF+源代码+书籍软件包 下载: 链接:https://pan.baidu.com/s/18yqCr7i9x_vTazuMPzL23Q 提取码:i ...

  9. Python 3网络爬虫开发实战书籍

    Python 3网络爬虫开发实战书籍,教你学会如何用Python 3开发爬虫   本书介绍了如何利用Python 3开发网络爬虫,书中首先介绍了环境配置和基础知识,然后讨论了urllib.reques ...

随机推荐

  1. 剑指 Offer

    3.1 找出数组中重复的数 来源:AcWing 题目描述 给定一个长度为 n 的整数数组 nums,数组中所有的数字都在 0∼n−1 的范围内. 数组中某些数字是重复的,但不知道有几个数字重复了,也不 ...

  2. shell与aw的简单交互示例

    先来看一段shell代码 word=“a test name” selectword=“test"lineitem=`echo "$word" | awk 'match( ...

  3. Azkaban的功能特点(二)

    Azkaban是什么?(一) 不多说,直接上干货! http://www.cnblogs.com/zlslch/category/938837.html Azkaban的功能特点 它具有如下功能特点: ...

  4. Nginx 开启多核cpu配置

    nginx默认是没有开启利用多核cpu的配置的.需要通过增加worker_cpu_affinity配置参数来充分利用多核cpu; 需要在nginx配置里添加 worker_processes 和 or ...

  5. arcengine geometry union操作

    以前得到的结果老是某一个,用下面的方法就可以获取合并后的结果 IGeometry pUnionGeo = null; var bFirst = true; foreach (IGeometry pGe ...

  6. 最大流bfs

    #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #i ...

  7. vs2013编译过程中,错误 59 error C4996: 'GetVersionExW': 被声明为已否决

    好几次碰到这个错误,必须mark 一下!!!!!Project Properties > Configuration Properties > C/C++ > General > ...

  8. nmon安装和使用介绍

    使用参考地址:百度中搜索 nmon 博客园 使用文档参考地址:http://nmon.sourceforge.net/pmwiki.php?n=Site.Documentation nmmon地址:h ...

  9. xcode或者mac自带颜色器选择rgb格式

    解决方法

  10. 机器学习(3)- 学习建议<误差出现如何解决?>

    根据Andrew Ng在斯坦福的<机器学习>视频做笔记,已经通过李航<统计学习方法>获得的知识不赘述,仅列出提纲. 1 学习建议 误差太大,如何改进? 使用更多的训练样本→解决 ...