爬虫开发python工具包介绍 (1)
发布日期:2021-09-11 05:52:46 浏览次数:18 分类:技术文章

本文共 7519 字,大约阅读时间需要 25 分钟。

本文来自网易云社区

作者:王涛

本文大纲:

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

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

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

  • 总结

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

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

Here we go!

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

一、简介requests与tornado

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

image

1、requests 基础

相信想快速上手爬虫的人都会选择python,并且选择requests库,请问获取百度首页源码要几步?

答:三步
第一步:下载和安装python
第二步:pip 安装 requests库
第三步:执行 python -c 'import requests; print requests.get("'

python -c 'import requests; print requests.get("http://www.baidu.com").content'
 
百度一下,你就知道 
 
 
 
 
  
 
 
 
 
 
    
 
 
 
 
更多产品    
 
 
 
关于百度 
About Baidu 

 
©2017 Baidu 
使用百度前必读  
 

     
2、requests高效抓取

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

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

image

为了程序简单,就直接多线程运行了,毕竟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 简介

[译:]

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 
` 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 
` 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 
`, prepares it and sends it.        Returns :class:`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) 
` 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+款云产品! 

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

相关文章:

【推荐】 
【推荐】 

转载地址:https://blog.csdn.net/weixin_34406061/article/details/86018047 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:.NET微服务调查结果
下一篇:python对象池模式

发表评论

最新留言

逛到本站,mark一下
[***.202.152.39]2024年04月03日 19时39分07秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

CentOs7命令行(静默)的方式安装oracle数据库 2019-04-27
基于VMware安装CentOs7的镜像 2019-04-27
PL/SQL数据库管理工具的使用 2019-04-27
史上最简单的spring-boot集成websocket的实现方式 2019-04-27
带你玩转属于自己的spring-boot-starter系列(一) 2019-04-27
带你玩转属于自己自己的spring-boot-starter系列(二) 2019-04-27
带你玩转属于自己的spring-boot-starter系列(三) 2019-04-27
基于SnowFlake算法如何让分库分表中不同的ID落在同一个库的算法的实现 2019-04-27
基于springboot的ShardingSphere5.X的分库分表的解决方案之分库解决方案(二) 2019-04-27
基于springboot的ShardingSphere5.X的分库分表的解决方案之分表解决方案(一) 2019-04-27
基于springboot的ShardingSphere5.X的分库分表的解决方案之关联查询解决方案(三) 2019-04-27
基于springboot的ShardingSphere5.X的分库分表的解决方案之基于seata的分布式事务的解决方案(十五) 2019-04-27
Linux文件管理参考 2019-04-27
FTP文件管理项目(本地云)项目日报(一) 2019-04-27
FTP文件管理项目(本地云)项目日报(二) 2019-04-27
FTP文件管理项目(本地云)项目日报(三) 2019-04-27
FTP文件管理项目(本地云)项目日报(四) 2019-04-27
【C++】勉强能看的线程池详解 2019-04-27
FTP文件管理项目(本地云)项目日报(五) 2019-04-27
FTP文件管理项目(本地云)项目日报(关于不定长包的测试) 2019-04-27