爬虫开发python工具包介绍 (1)
本文来自网易云社区
作者:王涛
本文大纲:
简易介绍今天要讲解的两个爬虫开发的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'
python -c 'import requests; print requests.get("http://www.baidu.com").content'<!DOCTYPE html>
<!--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>©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语句后开始继续执行。
import randomfrom tornado.ioloop import IOLoopfrom tornado import gen@gen.coroutinedef show_my_sleep(idx):
interval = random.uniform(5,20) print "[{}] is going to sleep {} seconds!".format(idx, interval) yield gen.sleep(interval) # 此处会作为中断点,交出代码运行权
print "[{}] wake up!!".format(idx)def main():
io_loop = IOLoop.current()
io_loop.spawn_callback(show_my_sleep, 1) # 下一次循环的时候调度这个函数
io_loop.spawn_callback(show_my_sleep, 2)
io_loop.spawn_callback(show_my_sleep, 3)
io_loop.spawn_callback(show_my_sleep, 4)
io_loop.start()if __name__ == "__main__":
main()
结果:
[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]
Tornado 是基于Python实现的异步网络框架,它采用非阻塞IO,可以支持成千上万的并发访问量,
所以非常适合于长轮询和Websocket, 以及其它需要持久连接的应用场景。Tornado 主要包含四个部分:- web框架,包括了RequestHandler(它可以用来创建WEB应用和各种支持的类)- 客户端、服务端侧的HTTP实现(包括HttpServer 和AsyncHttpClient)- 包含了 IOLoop和IOStream 的异步网络库,它们作为HTTP组件的内置块并且可以用来实现其它协议。- 协程库(tornado.gen),它使异步代码写起来比链式回调更直接。Tornado WEB框架和HTTP server 在一起可以作为WSGI的全栈替代。
在WSGI容器里可以使用Tornado web框架,也可以用Http server 作为其它WSGI框架的容器,不过任意一种组合都是有缺陷的。
为了充分发挥tornado的优势 ,你需要使用tornado 的web框架和http server.
我们在这里主要借用tornado的 httpclient和协程库,来实现单线程下并发网络请求。
Here, show you the code!
import tracebackfrom tornado.ioloop import IOLoopfrom tornado import genfrom tornado.curl_httpclient import CurlAsyncHTTPClientfrom tornado.httpclient import HTTPRequest@gen.coroutinedef fetch_url(url):
"""抓取url"""
try:
c = CurlAsyncHTTPClient() # 定义一个httpclient
req = HTTPRequest(url=url) # 定义一个请求
response = yield c.fetch(req) # 发起请求
print response.body
IOLoop.current().stop() # 停止ioloop线程
except: print traceback.format_exc()def main():
io_loop = IOLoop.current()
io_loop.spawn_callback(fetch_url, "http://www.baidu.com") # 添加协程函数到Ioloop循环中
io_loop.start()if __name__ == "__main__":
main()
4、tornado并发
这里简单讲,就是通过向ioloop中添加回调,来实现多个回调的并行调用。
def main():
io_loop = IOLoop.current()
io_loop.spawn_callback(fetch_url, "http://www.baidu.com") # 下一次循环的时候调度这个函数
'''
io_loop.spawn_callback(fetch_url, url1)
... ...
io_loop.spawn_callback(fetch_url, urln)
'''
io_loop.start()if __name__ == "__main__":
main()
简单介绍过两个应用包后,来详细介绍一下关键函数及参数。
二、requests 关键函数及参数
我们利用requests开发爬虫时,主要会用到 get,post 方法,另外,为了应对反爬虫策略,会添加一些自定义的http头信息,我们从这个应用角度介绍一下requests的两个关键函数get和post。
函数定义:
def get(url, params=None, **kwargs):
"""Sends a GET request. :param url: URL for the new :class:`Request` object.
:param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`.
:param \*\*kwargs: Optional arguments that ``request`` takes.
:return: :class:`Response <Response>` object
:rtype: requests.Response
""" kwargs.setdefault('allow_redirects', True) return request('get', url, params=params, **kwargs)
def post(url, data=None, json=None, **kwargs):
"""Sends a POST request. :param url: URL for the new :class:`Request` object.
:param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`.
:param json: (optional) json data to send in the body of the :class:`Request`.
:param \*\*kwargs: Optional arguments that ``request`` takes.
:return: :class:`Response <Response>` object
:rtype: requests.Response
""" return request('post', url, data=data, json=json, **kwargs)
我们可以看到,requests的get,post方法都会 调用 request函数,request函数定义如下:
def request(self, method, url, params=None,
data=None,
headers=None,
cookies=None,
files=None,
auth=None,
timeout=None,
allow_redirects=True,
proxies=None,
hooks=None,
stream=None,
verify=None,
cert=None,
json=None):
"""Constructs a :class:`Request <Request>`, prepares it and sends it.
Returns :class:`Response <Response>` object. :param method: method for the new :class:`Request` object.
:param url: URL for the new :class:`Request` object.
:param params: (optional) Dictionary or bytes to be sent in the query
string for the :class:`Request`.
:param data: (optional) Dictionary, bytes, or file-like object to send
in the body of the :class:`Request`.
:param json: (optional) json to send in the body of the
:class:`Request`.
:param headers: (optional) Dictionary of HTTP Headers to send with the
:class:`Request`.
:param cookies: (optional) Dict or CookieJar object to send with the
:class:`Request`.
:param files: (optional) Dictionary of ``'filename': file-like-objects``
for multipart encoding upload.
:param auth: (optional) Auth tuple or callable to enable
Basic/Digest/Custom HTTP Auth.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple
:param allow_redirects: (optional) Set to True by default.
:type allow_redirects: bool
:param proxies: (optional) Dictionary mapping protocol or protocol and
hostname to the URL of the proxy.
:param stream: (optional) whether to immediately download the response
content. Defaults to ``False``.
:param verify: (optional) whether the SSL cert will be verified.
A CA_BUNDLE path can also be provided. Defaults to ``True``.
:param cert: (optional) if String, path to ssl client cert file (.pem).
If Tuple, ('cert', 'key') pair.
:rtype: requests.Response
"""
网易云免费体验馆,0成本体验20+款云产品!
更多网易研发、产品、运营经验分享请访问网易云社区。
相关文章:
【推荐】 网易美学-系统架构系列1-分布式与服务化
【推荐】 Hi,这有一份风控体系建设干货
爬虫开发python工具包介绍 (1)的更多相关文章
- 爬虫开发python工具包介绍 (2)
本文来自网易云社区 作者:王涛 可选参数我们一一介绍一下: 参数 释义 示例 params 生成url中?号后面的查询Key=value 示例1: >>>payload = {'ke ...
- 爬虫开发python工具包介绍 (4)
本文来自网易云社区 作者:王涛 此处我们给出几个常用的代码例子,包括get,post(json,表单),带证书访问:Get 请求 @gen.coroutine def fetch_url(): ...
- 爬虫开发python工具包介绍 (3)
本文来自网易云社区 作者:王涛 :arg str url: URL to fetch :arg str method: HTTP method, e.g. " ...
- Python爬虫开发与项目实战
Python爬虫开发与项目实战(高清版)PDF 百度网盘 链接:https://pan.baidu.com/s/1MFexF6S4No_FtC5U2GCKqQ 提取码:gtz1 复制这段内容后打开百度 ...
- Python 3网络爬虫开发实战》中文PDF+源代码+书籍软件包
Python 3网络爬虫开发实战>中文PDF+源代码+书籍软件包 下载:正在上传请稍后... 本书书籍软件包为本人原创,在这个时间就是金钱的时代,有些软件下起来是很麻烦的,真的可以为你们节省很多 ...
- Python 3网络爬虫开发实战中文 书籍软件包(原创)
Python 3网络爬虫开发实战中文 书籍软件包(原创) 本书书籍软件包为本人原创,想学爬虫的朋友你们的福利来了.软件包包含了该书籍所需的所有软件. 因为软件导致这个文件比较大,所以百度网盘没有加速的 ...
- Python 3网络爬虫开发实战中文PDF+源代码+书籍软件包(免费赠送)+崔庆才
Python 3网络爬虫开发实战中文PDF+源代码+书籍软件包+崔庆才 下载: 链接:https://pan.baidu.com/s/1H-VrvrT7wE9-CW2Dy2p0qA 提取码:35go ...
- 《Python 3网络爬虫开发实战中文》超清PDF+源代码+书籍软件包
<Python 3网络爬虫开发实战中文>PDF+源代码+书籍软件包 下载: 链接:https://pan.baidu.com/s/18yqCr7i9x_vTazuMPzL23Q 提取码:i ...
- Python 3网络爬虫开发实战书籍
Python 3网络爬虫开发实战书籍,教你学会如何用Python 3开发爬虫 本书介绍了如何利用Python 3开发网络爬虫,书中首先介绍了环境配置和基础知识,然后讨论了urllib.reques ...
随机推荐
- 如何在spring环境中做单元测试
在测试类的上方加入以下注解 @RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("classpath:spring.xm ...
- matlab各向异性扩散滤波
主要是用来平滑图像的,克服了高斯模糊的缺陷,各向异性扩散在平滑图像时是保留图像边缘的(和双边滤波很像). 通常我们有将图像看作矩阵的,看作图的,看作随机过程的,记得过去还有看作力场的. 这次新鲜,将图 ...
- DockerSwarm 集群环境搭建
一.简介 1. 什么是docker swarm? Swarm 在 Docker 1.12 版本之前属于一个独立的项目,在 Docker 1.12 版本发布之后,该项目合并到了 Docker 中,成为 ...
- GraphicsMagick安装&make命令使用
0.0本过程为GraphicsMagick Linux版安装,通过典型的make编译安装. 未了支持png和jpg格式,首先请安装依赖.执行 yum install -y libpng-devel y ...
- DrawerLayout Demo
源码下载:http://download.csdn.net/detail/bx276626237/8882763
- PHP-PHPExcel用法详解
以下文章来源:diandian_520 http://blog.csdn.net/diandian_520/article/details/7827038 1.header header(" ...
- java代码(生成日历时间)
package test; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; p ...
- sparkmlib-相关系数
一.基本原理 在stat包中实现了皮尔逊(Pearson)与 斯皮尔曼(Spearman)两类相关系数的计算 (1)Pearson: (x,y)协方差/[(x标准方差)*(y标准方差)] 详情可以 ...
- webpack 使用流程
webpack loader 读文件的 脚手架 vue-cli: 自动化的小工具,帮咱们把项目的架子搭起来 -------------------------------------- 开发环境 n ...
- Robot Framework(十一) 执行测试用例——后处理输出
3.3后处理输出 在测试执行期间生成的XML输出文件可以在之后由rebot工具进行后处理,该工具是Robot Framework的组成部分.在测试执行期间生成测试报告和日志时会自动使用它,但在执行后也 ...