xml地图|网站地图|网站标签 [设为首页] [加入收藏]

您的位置:亚洲必赢 > 计算机尝试 > 【必赢亚洲手机下载】并发爬取,并发爬取智联

【必赢亚洲手机下载】并发爬取,并发爬取智联

发布时间:2019-05-24 06:45编辑:计算机尝试浏览(62)

    1 背景

    在那一密密麻麻开始前大家就说过,轻易的爬虫很轻巧,可是要完毕多个高速健壮的爬虫不是一个简易的作业,这一文山会海大家早已理解了爬虫相关的如下大旨知识点。

    必赢亚洲手机下载 1

    根据上边这几篇其实大家把爬虫当作本人方便的开辟工具来行使基本上是够了(比方老总让您定时留意观察自个儿做的采纳效率上线后的用户作为数据,方便开荒把握成效地下风险,那个实在我们就能够写个 Python 爬虫小程序去后台定时查,然后定时邮件发送到作者的邮箱,那样就毫无本身老年记者着那回事然后去上网页操作了),不过对于动态网页爬取我们还未深究、对于爬取数据管理我们也没追究、对于爬取品质难题大家也没追究。。。作者靠,还会有大多事物等待大家去发现,MLGB,那我们那1篇就先研究下 Python 爬虫的面世爬取,其实正是 Python 的出现,呜呜!

    就此探究那几个话题是为着缓和《Python3.X 爬虫实战(静态下载器与分析器)》【必赢亚洲手机下载】并发爬取,并发爬取智联招聘。一文中 LXml 解析爬取美图录美女图片网址的效用难题,你会发觉咱们上一篇中国和欧洲常程序的实践成效非常的低,爬取完这贰个妹子图供给很就,因为他们是逐1的,加上大家还并未有对大嫂图网址进行全站爬取,倘诺要全站爬取那正是个杰出恐怖的事体了,不信我们得以因此《Python3.X 爬虫实战(先爬起来嗨)》一文介绍的 site 格局查看那几个站点有多少页面能够爬取,如下:

    必赢亚洲手机下载 2

    那还不算非常多,但大家已经无法忍受这么慢的爬取速度了,所以大家将在想艺术减轻这些难题,也便是那1篇要搜求的主题素材,不过首先你得具有Python 并发编制程序的根基,若是还不 OK 能够看看和讯上 Python 之美的 Python 并发编制程序类别作品,讲的不错,恐怕去探访 Python 宗旨编制程序1书。

    小说首发个人博客:http://zmister.com/

    一、前言


          前些时间尝试爬取了微博云音乐的歌曲,本次准备爬取QQ音乐的歌曲音讯。天涯论坛云音乐歌曲列表是由此iframe显示的,能够依附Selenium获取到iframe的页面成分,

      而QQ音乐选用的是异步加载的不二法门,套路差别等,那是主流的页面加载格局,爬取有一点点难度,不过也是对团结的1个挑衅。

     

    图表来源于 unsplash

    二 Python 三.X 并发铺垫

    实则这一小节没供给存在的,不过为了补全就列出来了(注意:假如自身独具并发基础就直接移步 Part3并发爬虫实战)。对于程序的经过、线程关系及界其他概念实际上是不区分具体编制程序语言的,也就说如若大家过去在处理器基础、Unix 高档 C 语言编程、Java 编制程序、Android 编制程序等学习过进程与线程的概念,那么 Python 的出现也就好通晓了,唯一区别是她们的语法和 API 名字及用法不相同而已。

    Python三 使用 POSIX 包容的(pthreads)线程,提供了五个四线程编制程序模块,举个例子 _thread、threading、Queue、concurrent.futures 包等,其中 _thread、threading 允许大家创制管理线程,主要差别正是 _thread (从前Python 中的 thread,Python三 中早已不能够再使用 thread 模块,为了同盟Python三 将它重命名称为 _thread 了)只提供了主导的线程及锁帮忙;而 threading 提供了更为牛逼的线程管理机制;Queue 为大家提供了二个用以四线程共享数据的行列;concurrent.futures包从 Python三.二 开首被纳入了标准库,其提供的ThreadPoolExecutor 和 ProcessPoolExecutor 是对 threading 和 multiprocessing 的尖端抽象,揭破统1的接口来便于落成异步调用。

    相关小说:
    Python爬虫实战入门一:工具计划
    Python爬虫实战入门二:从3个简便的HTTP请求发轫
    Python爬虫实战入门3:轻松的HTML深入分析——爬取Tencent情报
    Python爬虫实战入门4:使用Cookie模拟登入——获取电子书下载链接
    Python爬虫实战入门5:获取JS动态内容—爬取乐乎
    Python爬虫实战入门6:进步爬虫功效—并发爬取智联合招生聘
    Python爬虫入门实战7:使用Selenium--以抓取QQ空间死党说说为例
    Python爬虫入门实战8:数据存储——MongoDB与MySQL

    2、Python爬取QQ音乐单曲


    从前看的慕课网的3个视频, 很好地解说了貌似编写爬虫的步调,大家也按这几个来。

    必赢亚洲手机下载 3

              爬虫步骤

    一.鲜明指标

    先是大家要刚强对象,本次爬取的是QQ音乐歌唱家刘德华(Andy Lau)的单曲。

    (百度完善)->深入分析目的(计谋:url格式(范围)、数据格式、网页编码)->编写代码->施行爬虫

    二.深入分析对象

     歌曲链接:

    从右侧的截图可以知道单曲采取分页的秘技排列歌曲新闻,每页呈现30条,总共30页。点击页码恐怕最右侧的">"会跳转到下一页,浏览器会向服务器发送ajax异步请求,从链接能够看看begin和num参数,分别代表发轫歌曲下标(截图是第2页,起首下标是30)和一页重返30条,服务器响应重返json格式的歌曲音讯(MusicJsonCallbacksinger_track({"code":0,"data":{"list":[{"Flisten_count1":......]})),假若只是独立想赢得歌曲信息,能够一贯拼接链接请求和分析再次回到的json格式的数据。这里不采纳直接深入分析数据格式的办法,笔者使用的是Python Selenium方式,每获得和剖判完1页的单曲音讯,点击 ">" 跳转到下一页继续剖析,直至解析并记下全体的单曲音信。最终呼吁各个单曲的链接,获取详细的单曲音信。

    必赢亚洲手机下载 4

     

    左边的截图是网页的源码,全数歌曲音信都在类名称叫mod_songlist的div浮层里面,类名叫songlist_list的严节列表ul下,种种子成分li展现1个单曲,类名叫songlist__album下的a标签,包罗单曲的链接,名称和时间长度等。

    必赢亚洲手机下载 5必赢亚洲手机下载 6

     

    三.编制代码

    1)下载网页内容,这里运用Python 的Urllib规范库,自己包装了八个download方法:

     1 def download(url, user_agent='wswp', num_retries=2):
     2     if url is None:
     3         return None
     4     print('Downloading:', url)
     5     headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'}
     6     request = urllib.request.Request(url, headers=headers)  # 设置用户代理wswp(Web Scraping with Python)
     7     try:
     8         html = urllib.request.urlopen(request).read().decode('utf-8')
     9     except urllib.error.URLError as e:
    10         print('Downloading Error:', e.reason)
    11         html = None
    12         if num_retries > 0:
    13             if hasattr(e, 'code') and 500 <= e.code < 600:
    14                 # retry when return code is 5xx HTTP erros
    15                 return download(url, num_retries-1)  # 请求失败,默认重试2次,
    16     return html
    

     

    贰)深入分析网页内容,这里运用第壹方插件BeautifulSoup,具体能够参见BeautifulSoup API 。

     1 def music_scrapter(html, page_num=0):
     2     try:
     3         soup = BeautifulSoup(html, 'html.parser')
     4         mod_songlist_div = soup.find_all('div', class_='mod_songlist')
     5         songlist_ul = mod_songlist_div[1].find('ul', class_='songlist__list')
     6         '''开始解析li歌曲信息'''
     7         lis = songlist_ul.find_all('li')
     8         for li in lis:
     9             a = li.find('div', class_='songlist__album').find('a')
    10             music_url = a['href']  # 单曲链接
    11             urls.add_new_url(music_url)  # 保存单曲链接
    12             # print('music_url:{0} '.format(music_url))
    13         print('total music link num:%s' % len(urls.new_urls))
    14         next_page(page_num 1)
    15     except TimeoutException as err:
    16         print('解析网页出错:', err.args)
    17         return next_page(page_num   1)
    18     return None
    
     1 def get_music():
     2      try:
     3         while urls.has_new_url():
     4             # print('urls count:%s' % len(urls.new_urls))
     5             '''跳转到歌曲链接,获取歌曲详情'''
     6             new_music_url = urls.get_new_url()
     7             print('url leave count:%s' % str( len(urls.new_urls) - 1))
     8             html_data_info = download(new_music_url)
     9             # 下载网页失败,直接进入下一循环,避免程序中断
    10             if html_data_info is None:
    11                 continue
    12             soup_data_info = BeautifulSoup(html_data_info, 'html.parser')
    13             if soup_data_info.find('div', class_='none_txt') is not None:
    14                 print(new_music_url, '   对不起,由于版权原因,暂无法查看该专辑!')
    15                 continue
    16             mod_songlist_div = soup_data_info.find('div', class_='mod_songlist')
    17             songlist_ul = mod_songlist_div.find('ul', class_='songlist__list')
    18             lis = songlist_ul.find_all('li')
    19             del lis[0]  # 删除第一个li
    20             # print('len(lis):$s' % len(lis))
    21             for li in lis:
    22                 a_songname_txt = li.find('div', class_='songlist__songname').find('span', class_='songlist__songname_txt').find('a')
    23                 if 'https' not in a_songname_txt['href']:  #如果单曲链接不包含协议头,加上
    24                     song_url = 'https:'   a_songname_txt['href']
    25                 song_name = a_songname_txt['title']
    26                 singer_name = li.find('div', class_='songlist__artist').find('a').get_text()
    27                 song_time =li.find('div', class_='songlist__time').get_text()
    28                 music_info = {}
    29                 music_info['song_name'] = song_name
    30                 music_info['song_url'] = song_url
    31                 music_info['singer_name'] = singer_name
    32                 music_info['song_time'] = song_time
    33                 collect_data(music_info)
    34      except Exception as err:  # 如果解析异常,跳过
    35          print('Downloading or parse music information error continue:', err.args)
    

    4.实施爬虫

    爬虫跑起来了,一页一页地去爬取专辑的链接,并保存到集合中,最后通过get_music()方法获取单曲的名称,链接,歌手名称和时长并保存到Excel文件中。
    

    咱俩早就学习 urllib、re、BeautifulSoup 那四个库的用法。但只是停留在商量层面上,还需试行来验证学习成果。因而,本文重要讲授如何行使我们刚刚的多少个库去实战。

    2-1 Python 3.X _thread 模块

    那是个受到我们放任的 Python 并发模块,在 Python 低版本中叫 thread,高版本为了合营叫 _thread,然则不引进应用了,具体不推荐的原由大致如下:

    • _thread 模块的同步原语只有3个,比较弱,threading 却有过多;
    • _thread 模块然后出现了越来越高等的 threading,你说您选哪些吧;
    • 不支持守护线程等,使用 _thread 模块对于经过该几时甘休基本不可能调控(主线程结束后具有线程被未有其余警示和清理的情形下强制甘休),而 threading 模块基本能够保证入眼子线程甘休后才脱离主线程;

    到底正是因为作者是个渣渣,精晓不了 _thread 模块,哈哈,所以小编没脸的选用了 threading 模块;多说无用,直接给段代码演示下啊,这段代码在种种语言的10二线程中都以特出,没啥万分的,如下: 

     1 import _thread
     2 import time
     3 '''
     4 #Python学习交流群125240963每天更新资料视频、大牛解答
     5 Python 3.X _thread 模块演示 Demo
     6 当注释掉 self.lock.acquire() 和 self.lock.release() 后运行代码会发现最后的 count 为 467195 等随机值,并发问题。
     7 当保留 self.lock.acquire() 和 self.lock.release() 后运行代码会发现最后的 count 为 1000000,锁机制保证了并发。
     8 time.sleep(5) 就是为了解决 _thread 模块的诟病,注释掉的话子线程没机会执行了
     9 '''
    10 class ThreadTest(object):
    11     def __init__(self):
    12         self.count = 0
    13         self.lock = None
    14 
    15     def runnable(self):
    16         self.lock.acquire()
    17         print('thread ident is ' str(_thread.get_ident()) ', lock acquired!')
    18         for i in range(0, 100000):
    19             self.count  = 1
    20         print('thread ident is '   str(_thread.get_ident())   ', pre lock release!')
    21         self.lock.release()
    22 
    23     def test(self):
    24         self.lock = _thread.allocate_lock()
    25         for i in range(0, 10):
    26             _thread.start_new_thread(self.runnable, ())
    27 
    28 if __name__ == '__main__':
    29     test = ThreadTest()
    30     test.test()
    31     print('thread is running...')
    32     time.sleep(5)
    33     print('test finish, count is:'   str(test.count))
    

    故而很直观的看见咯,确实值得唾弃,我们依旧看看 threading 吧。

    事先文章中所介绍的爬虫都以对单个U大切诺基L进行分析和爬取,url数量少不费时,不过一旦大家必要爬取的网页url有很多可能越多,这如何做?
    运用for循环对持有的url实行遍历访问?
    嗯,主张很好,不过如若url过多,爬取完全数的多少会不会太过头耗时了?
    对此大家能够运用并发来对U奥迪Q5L进行走访以爬取数据。
    诚如而言,在单机上我们使用三种并发方式:

    3、Python爬取QQ音乐单曲计算


    1.单曲行使的是分页格局,切换下一页是经过异步ajax请求从服务器获取json格式的数量并渲染到页面,浏览器地址栏链接是不变的,不能够由此拼接链接来请求。壹开头想过都通过Python Urllib库来模拟ajax请求,后来沉思还是用Selenium。Selenium能够很好地效法浏览器真实的操作,页面成分定位也很方便,模拟单击下1页,不断地切换单曲分页,再通过BeautifulSoup剖析网页源码,获取单曲信息。

     

    贰.url链接管理器,选择聚合数据结构来保存单曲链接,为何要选择集结?因为七个单曲或然来自同1专辑(专辑网站同样),那样能够减小请求次数。

     1 class UrlManager(object):
     2     def __init__(self):
     3         self.new_urls = set()  # 使用集合数据结构,过滤重复元素
     4         self.old_urls = set()  # 使用集合数据结构,过滤重复元素
     5     def add_new_url(self, url):
     6         if url is None:
     7             return
     8         if url not in self.new_urls and url not in self.old_urls:
     9             self.new_urls.add(url)
    10 
    11     def add_new_urls(self, urls):
    12         if urls is None or len(urls) == 0:
    13             return
    14         for url in urls:
    15             self.add_new_url(url)
    16 
    17     def has_new_url(self):
    18         return len(self.new_urls) != 0
    19 
    20     def get_new_url(self):
    21         new_url = self.new_urls.pop()
    22         self.old_urls.add(new_url)
    23         return new_url
    
     
    

    3.通过Python第一方插件openpyxl读写Excel13分利于,把单曲音讯通过Excel文件能够很好地保存起来。

    1 def write_to_excel(self, content):
    2     try:
    3         for row in content:
    4             self.workSheet.append([row['song_name'], row['song_url'], row['singer_name'], row['song_time']])
    5         self.workBook.save(self.excelName)  # 保存单曲信息到Excel文件
    6     except Exception as arr:
    7         print('write to excel error', arr.args)
    

    一 明确爬取指标

    其它网站皆可爬取,就看你要不要爬取而已。这一次选用的爬取指标是当当网,爬取内容是 以 Python 为第贰字找寻出来的页面中全部书籍的新闻。具体如下图所示:

    这次爬取结果有③项:

    • 书籍的书皮图片
    • 图书的书名
    • 书本的链接页面
      谈起底把那叁项内容保留到 csv 文件中。

    2-2 Python 3.X threading 模块

    至于 threading 模块提供的对象实际大家能够平昔看看 threading.py 源码的__all__概念,里面有现实列举,如下:

    1 __all__ = ['get_ident', 'active_count', 'Condition', 'current_thread',
    2            'enumerate', 'main_thread', 'TIMEOUT_MAX',
    3            'Event', 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread',
    4            'Barrier', 'BrokenBarrierError', 'Timer', 'ThreadError',
    5            'setprofile', 'settrace', 'local', 'stack_size']
    

    看了那些定义和官方网站 API 后随手搜到这篇文章不错(点自身翻看),感兴趣的能够团结去探讨下咯,上边我们先交付 threading 模块下 Thread 类的一般用法,如下: 

     1 import threading
     2 from threading import Thread
     3 import time
     4 '''
     5 Python 3.X threading 模块演示 Demo
     6 #Python学习交流群125240963每天更新资料大牛指导
     7 
     8 threading 的 Thread 类基本使用方式(继承重写 run 方法及直接传递方法)
     9 '''
    10 class NormalThread(Thread):
    11     '''
    12     重写类比 Java 的 Runnable 中 run 方法方式
    13     '''
    14     def __init__(self, name=None):
    15         Thread.__init__(self, name=name)
    16         self.counter = 0
    17 
    18     def run(self):
    19         print(self.getName()   ' thread is start!')
    20         self.do_customer_things()
    21         print(self.getName()   ' thread is end!')
    22 
    23     def do_customer_things(self):
    24         while self.counter < 10:
    25             time.sleep(1)
    26             print('do customer things counter is:' str(self.counter))
    27             self.counter  = 1
    28 
    29 
    30 def loop_runner(max_counter=5):
    31     '''
    32     直接被 Thread 调用方式
    33     '''
    34     print(threading.current_thread().getName()   " thread is start!")
    35     cur_counter = 0
    36     while cur_counter < max_counter:
    37         time.sleep(1)
    38         print('loop runner current counter is:'   str(cur_counter))
    39         cur_counter  = 1
    40     print(threading.current_thread().getName()   " thread is end!")
    41 
    42 
    43 if __name__ == '__main__':
    44     print(threading.current_thread().getName()   " thread is start!")
    45 
    46     normal_thread = NormalThread("Normal Thread")
    47     normal_thread.start()
    48 
    49     loop_thread = Thread(target=loop_runner, args=(10,), name='LOOP THREAD')
    50     loop_thread.start()
    51 
    52     loop_thread.join()
    53     normal_thread.join()
    54 
    55     print(threading.current_thread().getName()   " thread is end!")
    

    哪些,最直白的感触便是再也不用像 _thread 那样让主线程预估甘休时间等待子线程结束,使用 Thread 类未来直接能够行使 join 格局等待子线程停止,当然还也可能有其他艺术,本人能够商讨;大家会开采其三种写法和 Java 线程特别类似,很棒,上面我们再交给容易的同台孝鱼理案例,如下: 

    '''
    Python 3.X threading 模块演示 Demo
    
    threading 锁同步机制
    当注释掉 self.lock.acquire() 和 self.lock.release() 后运行代码会发现最后的 count 为 467195 等,并发问题。
    当保留 self.lock.acquire() 和 self.lock.release() 后运行代码会发现最后的 count 为 1000000,锁机制保证了并发。
    '''
    import threading
    from threading import Thread
    
    class LockThread(Thread):
        count = 0
    
        def __init__(self, name=None, lock=None):
            Thread.__init__(self, name=name)
            self.lock = lock
    
        def run(self):
            self.lock.acquire()
            print('thread is ' threading.current_thread().getName() ', lock acquired!')
            for i in range(0, 100000):
                LockThread.count  = 1
            print('thread is ' threading.current_thread().getName() ', pre lock release!')
            self.lock.release()
    
    
    if __name__ == '__main__':
        threads = list()
        lock = threading.Lock()
        for i in range(0, 10):
            thread = LockThread(name=str(i), lock=lock)
            thread.start()
            threads.append(thread)
    
        for thread in threads:
            thread.join()
        print('Main Thread finish, LockThread.count is:' str(LockThread.count))
    

    对此一般的产出同步运用 Lock 就足足了,轻易吗,关于其余的锁机制(下边__all__ 的定义)本身能够参照其余材质进行学习,这里点到截止,下边大家再来看看爬虫中常用的线程优先级队列,如下: 
    必赢亚洲手机下载 7 
    Python叁 的 Queue 模块提供了1道、线程安全队列类,包蕴先入先骑行列 Queue、后入先出游列 LifoQueue 和预先级队列 PriorityQueue,那个队列都落到实处了锁机制,能够在八线程中央直机关接使用,也得以用那一个队列来贯彻线程间的同步,上面给出三个简练可是杰出的示范(生产消费者难题),如下: 

     1 from queue import Queue
     2 from random import randint
     3 from threading import Thread
     4 from time import sleep
     5 '''
     6 Python 3.X threading 与 Queue 结合演示 Demo
     7 经典的并发生产消费者模型
     8 '''
     9 
    10 class TestQueue(object):
    11     def __init__(self):
    12         self.queue = Queue(2)
    13 
    14     def writer(self):
    15         print('Producter start write to queue.')
    16         self.queue.put('key', block=1)
    17         print('Producter write to queue end. size is:' str(self.queue.qsize()))
    18 
    19     def reader(self):
    20         value = self.queue.get(block=1)
    21         print('Consumer read from queue end. size is:' str(self.queue.qsize()))
    22 
    23     def producter(self):
    24         for i in range(5):
    25             self.writer()
    26             sleep(randint(0, 3))
    27 
    28     def consumer(self):
    29         for i in range(5):
    30             self.reader()
    31             sleep(randint(2, 4))
    32 
    33     def go(self):
    34         print('TestQueue Start!')
    35         threads = []
    36         functions = [self.consumer, self.producter]
    37         for func in functions:
    38             thread = Thread(target=func, name=func.__name__)
    39             thread.start()
    40             threads.append(thread)
    41         for thread in threads:
    42             thread.join()
    43         print('TestQueue Done!')
    44 
    45 if __name__ == '__main__':
    46     TestQueue().go()
    

    可以看看,一般与爬虫相关常见和常用的 Python3线程相关东西根本就地方那些,当然还大概有一点高等的用法和高等的线程类大家从不涉及,这么些须求我们和好去积存和依据本身爬虫须求选用适宜的线程协助类;这里大家篇幅有限不再举办,因为对此任何语言用好线程并发本来正是3个老大有深度的主旋律,涉及的题目大概多,不过对于一般工作以来上边包车型客车足矣。

    • 多线程(threading)
    • 多进程(multiprocessing)
    • 协程(gevent)

    四、后语


    最终依旧要庆祝下,毕竟成功把QQ音乐的单曲音讯爬取下来了。此次能够得逞爬取单曲,Selenium功不可没,本次只是使用了selenium一些大致的意义,后续会更深切学习Selenium,不只有在爬虫方面还应该有UI自动化。

    一连还要求优化的点:

    一.下载的链接相比较多,二个3个下载起来比异常的慢,前边准备用八线程并发下载。

    二.下载速度过快,为了制止服务器禁止使用IP,前边还要对于同1域名访问过于频仍的题目,有个等待机制,每一种请求之间有个等待间隔。

    三. 深入分析网页是三个第2的历程,能够利用正则表达式,BeautifulSoup和lxml,如今接纳的是BeautifulSoup库, 在功用方面,BeautifulSoup没lxml成效高,后面会尝试使用lxml。

     

    二 爬取进程

    总所周知,各种站点的页面 DOM 树是区别的。所以大家需求先对爬取页面实行分析,再鲜明自个儿要拿走的开始和结果,再定义程序爬取内容的规则。

    贰-3 Python 三.X 进度模块

    地点大家介绍了 Python叁 的 thread 并发相关基础,大家都知晓除过10二线程还应该有多进度,其内部存款和储蓄器空间划分等机制都以差异的,那是在其余语言大家都领会的。可是在 Python 中借使大家想尽量利用多核 CPU 能源,这就得利用多进程,Python 给大家提供了充足好用的多进度模块包 multiprocessing,其扶助子进度、通讯和共享数据等工具操作,十分厉害。

    上面先来看下 multiprocessing 的 Process 一般用法套路吧(其实完全类似 threading 用法,只可是含义和精神分化而已),如下: 

     1 import multiprocessing
     2 import time
     3 from multiprocessing import Process
     4 '''
     5 Python 3.X multiprocess 模块演示 Demo
     6 其实完全类似 threading 用法,只不过含义和实质不同而已
     7 multiprocess 的 Process 类基本使用方式(继承重写 run 方法及直接传递方法)
     8 '''
     9 class NormalProcess(Process):
    10     def __init__(self, name=None):
    11         Process.__init__(self, name=name)
    12         self.counter = 0
    13 
    14     def run(self):
    15         print(self.name   ' process is start!')
    16         self.do_customer_things()
    17         print(self.name   ' process is end!')
    18 
    19     def do_customer_things(self):
    20         while self.counter < 10:
    21             time.sleep(1)
    22             print('do customer things counter is:' str(self.counter))
    23             self.counter  = 1
    24 
    25 
    26 def loop_runner(max_counter=5):
    27     print(multiprocessing.current_process().name   " process is start!")
    28     cur_counter = 0
    29     while cur_counter < max_counter:
    30         time.sleep(1)
    31         print('loop runner current counter is:'   str(cur_counter))
    32         cur_counter  = 1
    33     print(multiprocessing.current_process().name   " process is end!")
    34 
    35 
    36 if __name__ == '__main__':
    37     print(multiprocessing.current_process().name   " process is start!")
    38     print("cpu count:" str(multiprocessing.cpu_count()) ", active chiled count:" str(len(multiprocessing.active_children())))
    39     normal_process = NormalProcess("NORMAL PROCESS")
    40     normal_process.start()
    41 
    42     loop_process = Process(target=loop_runner, args=(10,), name='LOOP PROCESS')
    43     loop_process.start()
    44 
    45     print("cpu count:"   str(multiprocessing.cpu_count())   ", active chiled count:"   str(len(multiprocessing.active_children())))
    46     normal_process.join()
    47     loop_process.join()
    48     print(multiprocessing.current_process().name   " process is end!")
    

    怎么着,给出的二种 Process 使用方法很像上面包车型客车Thread,只是含义和规律及内部存款和储蓄器概念有了分别。有了那些基础大家1致能够来探视 Process 的并发锁和多进程数据共享机制使用(与 Thread 的内存区别,任何语言通用),如下: 

     1 '''
     2 Python 3.X multiprocess 模块演示 Demo
     3 
     4 multiprocess 锁同步机制及进程数据共享机制
     5 当注释掉 self.lock.acquire() 和 self.lock.release() 后运行代码会发现最后的 count 为 467195 等,并发问题。
     6 当保留 self.lock.acquire() 和 self.lock.release() 后运行代码会发现最后的 count 为 1000000,锁机制保证了并发。
     7 '''
     8 import multiprocessing
     9 from multiprocessing import Process
    10 
    11 class LockProcess(Process):
    12     def __init__(self, name=None, lock=None, m_count=None):
    13         Process.__init__(self, name=name)
    14         self.lock = lock
    15         self.m_count = m_count
    16 
    17     def run(self):
    18         self.lock.acquire()
    19         print('process is ' multiprocessing.current_process().name ', lock acquired!')
    20         #性能问题,100000次循环,所以这里优化为先从多进程共享拿出来计算完再放回多进程共享
    21         count = self.m_count.value;
    22         for i in range(0, 100000):
    23             count  = 1
    24         self.m_count.value = count
    25         print('process is ' multiprocessing.current_process().name ', pre lock release!')
    26         self.lock.release()
    27 
    28 
    29 if __name__ == '__main__':
    30     processes = list()
    31     lock = multiprocessing.Lock()
    32     m_count = multiprocessing.Manager().Value('count', 0)
    33 
    34     for i in range(0, 10):
    35         process = LockProcess(name=str(i), lock=lock, m_count=m_count)
    36         process.start()
    37         processes.append(process)
    38 
    39     for process in processes:
    40         process.join()
    41     print('Main Process finish, LockProcess.count is:'   str(m_count.value))
    

    咦哎呀,矫情一把,受不了本身,都和 threading 类似是3个套路,唯壹不一致都以以为线程和进程本质差距导致的,而利用方式却没分别,所以 multiprocessing 的 Queue 类似 threading 的,不再比如了,具体和煦实战吧。

    对此上述两种方法的现实性概念解释和阐明,各位能够活动网络寻找理解,相信会比自身解释得知道,所以在此就难堪它们进行讲解表明了。
    本连串小说有五个首要,二个是实战,一个是入门,既为实战,理论性的东西就讲述得相比较少;既为入门,所讲述的都以简单易懂易操作的东西,高深的技巧还请入门之后自行查究,那样也会成长得越来越快。
    那便是说上边,初始并发爬取的实战入门,以多进度为例,并发爬取智联合招生聘的招聘音讯。
    ** 一、分析UCRUISERL和页面结构**
    一、寻找全国限制内岗位名包涵“Python”的职位招聘
    大家不分职业类型、不分行当连串,职业地点选为全国,职位名字为“Python”,对招聘音讯举行查找,结果如下图:

    2.1 确定 URL 地址

    我们能够透过动用浏览器来规定U福睿斯L 地址,为 urllib 发起呼吁提供进口地址。接下来,大家就一步步来规定请求地址。
    寻找结果页面为 一 时,U奥德赛L 地址如下:

    查找结果页面为 三 时,U途乐L 地址如下:

    检索结果页面为 贰1 时,即最终壹页,UBMWX伍L 地址如下:

    从地点的图样中,我们发掘 UTucsonL 地址的差异就在于 page_index 的值,所以 U本田CR-VL 地址最后为 http://search.dangdang.com/?key=python&act=input&show=big&page_index=。而 page_index 的值,大家得以通过轮回依次在地点前边增添。由此, urllib 请求代码能够这么写:

        # 爬取地址, 当当所有 Python 的书籍, 一共是 21 页
        url = "http://search.dangdang.com/?key=python&act=input&show=big&page_index="
    
        index = 1
        while index <= 21:
            # 发起请求
            request = urllib.request.Request(url=url str(index), headers=headers)
            response = urllib.request.urlopen(request)
            index = index   1
            # 解析爬取内容
            parseContent(response)
            time.sleep(1)  # 休眠1秒
    

    2-4 Python 3.X 并发池

    从 Python 并发线程到并发进度一步一步走到这你会意识 Python 规范库给我们提供的 _thread、threading 和 multiprocessing 模块是可怜棒的,可是你有未有想过(在其余语言也会遭遇,譬喻 CJava 等)在其实项目中常见的累累创造、销毁线程大概经过是1件拾分消耗电源的政工,所以池的概念就那样诞生了(空间换时间)。幸而Python三.二 开首内置规范库为大家提供了 concurrent.futures 模块,模块包涵了 ThreadPoolExecutor 和 ProcessPoolExecutor 多个类(其基类是 Executor 抽象类,不可直接使用),实现了对 threading 和 multiprocessing 的高档抽象,对编写线程池、进度池提供了第二手的扶助,大家只用将相应的 tasks 放入线程池、进度池中让其机动调节而不用自身去保养 Queue 来担心死锁难点。

    先来看看线程池样例: 

    '''
    Python 3.X ThreadPoolExecutor 模块演示 Demo
    '''
    import concurrent
    from concurrent.futures import ThreadPoolExecutor
    from urllib import request
    
    class TestThreadPoolExecutor(object):
        def __init__(self):
            self.urls = [
                'https://www.baidu.com/',
                'http://blog.jobbole.com/',
                'http://www.csdn.net/',
                'https://juejin.im/',
                'https://www.zhihu.com/'
            ]
    
        def get_web_content(self, url=None):
            print('start get web content from: ' url)
            try:
                headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64)"}
                req = request.Request(url, headers=headers)
                return request.urlopen(req).read().decode("utf-8")
            except BaseException as e:
                print(str(e))
                return None
            print('get web content end from: '   str(url))
    
        def runner(self):
            thread_pool = ThreadPoolExecutor(max_workers=2, thread_name_prefix='DEMO')
            futures = dict()
            for url in self.urls:
                future = thread_pool.submit(self.get_web_content, url)
                futures[future] = url
    
            for future in concurrent.futures.as_completed(futures):
                url = futures[future]
                try:
                    data = future.result()
                except Exception as e:
                    print('Run thread url (' url ') error. ' str(e))
                else:
                    print(url 'Request data ok. size=' str(len(data)))
            print('Finished!')
    
    if __name__ == '__main__':
        TestThreadPoolExecutor().runner()
    

    再来看看进度池实例,如下: 

     1 '''
     2 Python 3.X ProcessPoolExecutor 模块演示 Demo
     3 '''
     4 import concurrent
     5 from concurrent.futures import ProcessPoolExecutor
     6 from urllib import request
     7 
     8 class TestProcessPoolExecutor(object):
     9     def __init__(self):
    10         self.urls = [
    11             'https://www.baidu.com/',
    12             'http://blog.jobbole.com/',
    13             'http://www.csdn.net/',
    14             'https://juejin.im/',
    15             'https://www.zhihu.com/'
    16         ]
    17 
    18     def get_web_content(self, url=None):
    19         print('start get web content from: ' url)
    20         try:
    21             headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64)"}
    22             req = request.Request(url, headers=headers)
    23             return request.urlopen(req).read().decode("utf-8")
    24         except BaseException as e:
    25             print(str(e))
    26             return None
    27         print('get web content end from: '   str(url))
    28 
    29     def runner(self):
    30         process_pool = ProcessPoolExecutor(max_workers=4)
    31         futures = dict()
    32         for url in self.urls:
    33             future = process_pool.submit(self.get_web_content, url)
    34             futures[future] = url
    35 
    36         for future in concurrent.futures.as_completed(futures):
    37             url = futures[future]
    38             try:
    39                 data = future.result()
    40             except Exception as e:
    41                 print('Run process url (' url ') error. ' str(e))
    42             else:
    43                 print(url 'Request data ok. size=' str(len(data)))
    44         print('Finished!')
    45 
    46 if __name__ == '__main__':
    47     TestProcessPoolExecutor().runner()
    

    嗳,任何编制程序语言都是互通的,真的是如此,你只要深切了解壹门语言,其余的都很轻便,要适应的只是语法;对于 Python 3 的出现其实还也有十分的多知识点要求我们研究的,比如异步 IO、各类风味锁等等,大家要基于自身的需求去挑选使用11分的产出管理,唯有这么才是最合适的,同理可得学习并发就一个套路—–实战观察思索。

    咱俩注意图中八个红框的新闻:

    2.二 分明爬取节点

    有了 U悍马H2L 地址,就能够应用 urllib 获取到页面包车型大巴 html 内容。到了那步,我们就须求找到爬取的节点的规则,以便于 BeautifulSoup 地深入分析。为了化解这几个标题,将在祭出大招 —— Chrome 浏览器的开荒者功用(按下 F1二 键就会开发银行)。大家按下 F12键盘,依次对每本书进行成分检查(在页面使用鼠标右键,点击“检查”就可以),具体结果如下:

    从上海体育场所能够查出深入分析规则:每本书的节点是三个 a 标签,a 标签具有title,href,子标签 img 的 src 多少个属性,那3者分别对应书名、书的链接页面、书的封图。看到此间也需你不会小振撼,惊叹那不就是大家要感兴趣的内容吗?获得深入分析规则,编写BeautifulSoup 深入分析代码就有了思路,具体代码如下:

    # 提取爬取内容中的 a 标签, 例如:
    # <a
    #     class="pic" dd_name="单品图片"
    #     ddclick="act=normalResult_picture&pos=23648843_53_2_q"
    #     href="http://product.dangdang.com/23648843.html"
    #     name="itemlist-picture"
    #     target="_blank" title="
    #     趣学Python――教孩子学编程 ">
    #
    #   <img
    #       alt=" 趣学Python――教孩子学编程 "
    #       data-original="http://img3x3.ddimg.cn/20/34/23648843-1_b_0.jpg"
    #       src="images/model/guan/url_none.png"/>
    # </a>
    soup = BeautifulSoup(response)
    books = soup.find_all('a', class_='pic')
    print(books)
    

    运营结果如下:

    那评释刚才制定规则是毋庸置疑爬取大家所需的剧情。

    本文由亚洲必赢发布于计算机尝试,转载请注明出处:【必赢亚洲手机下载】并发爬取,并发爬取智联

    关键词: python Python3... 爬虫

上一篇:js上手教程,js实战详解

下一篇:没有了