python之路 -- 爬虫 -- 高性能相关

高性能爬虫方案:

  多进程

  多线程

  利用“异步非阻塞”模块实现单线程并发请求。

本质

 1 sk = socket()
 2 # 阻塞
 3 sk.connect((‘www.cnblogs.com‘,80))
 4
 5 sk.sendall(b"GET /wupeiqi http1.1\r\n.....\r\n\r\n")
 6 sk.sendall(b"POST /wupeiqi http1.1\r\n.....\r\n\r\nuser=alex&pwd=123")
 7
 8 # 阻塞
 9 data = sk.recv(8096)
10
11 sk.close()

IO多路复用:

  监听多个socket是否发生变化

IO多路复用的作用:

  1.select,内部循环检测socket是否发生变化;最多只能检测1024个socket

  2.poll,内部循环检测socket是否发生变化;检测socket数不限

  3.epoll,通过回调的方式检测socket是否发生变化;检测socket数不限

什么是异步非阻塞?

非阻塞:

   不等待(可能会报错,捕捉异常)
   代码:
    sk = socket.socket()
    sk.setblocking(False)
异步:
  回调,当达到某个指定的状态之后,自动调用特定函数。

如何自定义异步非阻塞模块?   

本质:socket+IO多路复用

  基于socket设置setblocking和IO多路复用来实现。
  爬虫发送Http请求本质创建socket对象;
  IO多路复用"循环"监听socket是否发生变化,一旦发生变化, 我们可以自定义操作(触发某个函数的执行)

 什么是协程?

  1. 是“微线程”,不存在;是由程序员人为创造出来并控制程序:先执行某段代码、再跳到某处执行某段代码。
  2.如果遇到非IO请求来回切换:性能更低。

  3. 如果遇到IO(耗时)请求来回切换:性能高、实现并发(本质上利用IO等待的过程,再去干一些其他的事)

通过yield实现一个协程:

def func1():

                        print(‘adsfasdf‘)
                        print(‘adsfasdf‘)
                        print(‘adsfasdf‘)
                        yield 1
                        print(‘adsfasdf‘)
                        print(‘adsfasdf‘)
                        print(‘adsfasdf‘)

                        yield 2
                        yield 3
                        yield 4

                    def func2():
                        print(‘adsfasdf‘)
                        print(‘adsfasdf‘)
                        print(‘adsfasdf‘)
                        yield 11
                        yield 12
                        yield 19

                    g1=func1()
                    g2=func2()

                    g1.send(None)
                    g1.send(None)
                    g2.send(None)

通过greenlet模块实现一个协程:

from greenlet import greenlet

                    def test1():
                        print 12
                        gr2.switch()
                        print 34
                        gr2.switch()

                    def test2():
                        print 56
                        gr1.switch()
                        print 78

                    gr1 = greenlet(test1)
                    gr2 = greenlet(test2)
                    gr1.switch()

Python内置以及第三方模块提供异步IO请求模块,使用简便大大提高效率,而对于异步IO请求的本质则是【非阻塞Socket】+【IO多路复用】:

 常用的3种:

import asyncio
import requests

@asyncio.coroutine
def fetch_async(func, *args):
    loop = asyncio.get_event_loop()
    future = loop.run_in_executor(None, func, *args)
    response = yield from future
    print(response.url, response.content)

tasks = [
    fetch_async(requests.get, ‘http://www.cnblogs.com/wupeiqi/‘),
    fetch_async(requests.get, ‘http://dig.chouti.com/pic/show?nid=4073644713430508&lid=10273091‘)
]

loop = asyncio.get_event_loop()
results = loop.run_until_complete(asyncio.gather(*tasks))
loop.close()

asyncio+requests

import gevent
import requests
from gevent import monkey

monkey.patch_all()

def fetch_async(method, url, req_kwargs):
    print(method, url, req_kwargs)
    response = requests.request(method=method, url=url, **req_kwargs)
    print(response.url, response.content)

# ##### 发送请求 #####
gevent.joinall([
    gevent.spawn(fetch_async, method=‘get‘, url=‘https://www.python.org/‘, req_kwargs={}),
    gevent.spawn(fetch_async, method=‘get‘, url=‘https://www.yahoo.com/‘, req_kwargs={}),
    gevent.spawn(fetch_async, method=‘get‘, url=‘https://github.com/‘, req_kwargs={}),
])

# ##### 发送请求(协程池控制最大协程数量) #####
# from gevent.pool import Pool
# pool = Pool(None)
# gevent.joinall([
#     pool.spawn(fetch_async, method=‘get‘, url=‘https://www.python.org/‘, req_kwargs={}),
#     pool.spawn(fetch_async, method=‘get‘, url=‘https://www.yahoo.com/‘, req_kwargs={}),
#     pool.spawn(fetch_async, method=‘get‘, url=‘https://www.github.com/‘, req_kwargs={}),
# ])

4.gevent + requests

gevent+requests

                from twisted.web.client import getPage, defer
                from twisted.internet import reactor

                def all_done(arg):
                    reactor.stop()

                def callback(contents):
                    print(contents)

                d_list = []

                url_list = [‘http://www.bing.com‘, ‘http://www.baidu.com‘, ]
                for url in url_list:
                    d = getPage(bytes(url, encoding=‘utf8‘))
                    d.addCallback(callback)

                    d_list.append(d)

                # 用于检查是否页面已经全部下载完成,如果已下载完成那么,就停止循环。
                dlist = defer.DeferredList(d_list)
                dlist.addBoth(all_done) #

                reactor.run()

Twisted示例

原文地址:https://www.cnblogs.com/aberwang/p/9301746.html

时间: 2024-11-09 10:22:26

python之路 -- 爬虫 -- 高性能相关的相关文章

爬虫高性能相关

高性能相关 如何实现多个任务的同时进行 而且还效率高 串行实现 效率最低最不可取 import requests urls = [ 'http://www.baidu.com/', 'https://www.cnblogs.com/', 'https://www.cnblogs.com/news/', 'https://cn.bing.com/', 'https://stackoverflow.com/', ] for url in urls: response = requests.get(u

python之路 - 爬虫

网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本.另外一些不常使用的名字还有蚂蚁.自动索引.模拟程序或者蠕虫. Scrapy Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 其可以应用在数据挖掘,信息处理或存储历史数据等一系列的程序中. 其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的, 也可以应用在获取API所返回的数据(例如 Amazon Associates Web

爬虫高性能相关(主要基于异步io)

一背景常识 爬虫的本质就是一个socket客户端与服务端的通信过程,如果我们有多个url待爬取,采用串行的方式执行,只能等待爬取一个结束后才能继续下一个,效率会非常低. 需要强调的是:串行并不意味着低效,如果串行的都是纯计算的任务,那么cpu的利用率仍然会很高,之所以爬虫程序的串行低效,是因为爬虫程序是明显的IO密集型程序. 关于IO模型详见链接:http://www.cnblogs.com/linhaifeng/articles/7454717.html 那么该如何提高爬取性能呢? 二同步,异

python之路 -- 爬虫 -- Scrapy入门

Scrapy Scrapy 是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 其可以应用在数据挖掘,信息处理或存储历史数据等一系列的程序中.其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的, 也可以应用在获取API所返回的数据(例如 Amazon Associates Web Services ) 或者通用的网络爬虫.Scrapy用途广泛,可以用于数据挖掘.监测和自动化测试. 下面是Scrapy的架构,包括组件以及在系统中发生的数据流的概览(绿色箭头所示).  数据流 Scra

python之路--爬虫第二篇

内容简介:基于flask框架实现web微信的登录以及收发消息. 实现思路: 1.获取验证码,并检测是否在手机端扫码并确认登录(长轮询) 2.用户数据初始化获取的授权信息,并根据获取的授权信息获取联系人信息 3.发送消息,根据接受者的ID,并携带登陆授权的认证发送POST请求 4.接受消息,用长轮询的方式,去想服务器端发送求,并检测返回值中的'selector'值为0代表无新消息,2代表有新消息.无论为'0'or'2',都会接着发长轮询请求,如果为'2'就会向服务端请求新消息的内容. 需要注意的事

python之路——爬虫实例

urlController.py import bsController from urllib import request class SpiderMain(object): def __init__(self): self.header = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11', 'Ac

python之路_django ORM相关补充

一.非django项目文件执行ORM 在不启动django项目的情况下,我们是否可以进行ORM操作呢?当然不行.因为所有的ORM操作都必须是要连接数据库的.但是我们有这样的一个需求:想在一个文件中执行ORM.该如何实现呢?参考如下实例: import os import sys import django sys.path.append(r'C:\Users\Administrator\PycharmProjects\s6day109') #将当前djang项目路径添加到环境 os.chdir(

Python之路【第十九篇】:爬虫

Python之路[第十九篇]:爬虫 网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本.另外一些不常使用的名字还有蚂蚁.自动索引.模拟程序或者蠕虫. Requests Python标准库中提供了:urllib.urllib2.httplib等模块以供Http请求,但是,它的 API 太渣了.它是为另一个时代.另一个互联网所创建的.它需要巨量的工作,甚至包括各种方法覆盖,来完成最简单的任务. import

Python之路【第五篇】:面向对象和相关

Python之路[第五篇]:面向对象及相关 面向对象基础 基础内容介绍详见一下两篇博文: 面向对象初级篇 面向对象进阶篇 其他相关 一.isinstance(obj, cls) 检查是否obj是否是类 cls 的对象 1 2 3 4 5 6 class Foo(object):     pass obj = Foo() isinstance(obj, Foo) 二.issubclass(sub, super) 检查sub类是否是 super 类的派生类 1 2 3 4 5 6 7 class F