今天宠物迷的小编给各位宠物饲养爱好者分享爬虫难度排行的宠物知识,其中也会对有没有易懂的 Python 多线程爬虫代码(有没有易懂的 python 多线程爬虫代码下载)进行专业的解释,如果能碰巧解决你现在面临的宠物相关问题,别忘了关注本站哦,现在我们开始吧!
Python 在程序并行化方面多少有些声名狼藉。撇开技术上的问题,例如线程的实现和 GIL1,我觉得错误的教学指导才是主要问题。常见的经典 Python 多线程、多进程教程多显得偏“重”。而且往往隔靴搔痒,没有深入探讨日常工作中最有用的内容。
传统的例子
简单搜索下“Python 多线程教程”,不难发现几乎所有的教程都给出涉及类和队列的例子:
#Example.py'''
Standard Producer/Consumer Threading Pattern
'''import time
import threading
import Queue
class Consumer(threading.Thread):
def __init__(self, queue):
threading.Thread.__init__(self)
self._queue = queue
def run(self):
while True:
# queue.get() blocks the current thread until
# an item is retrieved.
msg = self._queue.get()
# Checks if the current message is
# the "Poison Pill"
if isinstance(msg, str) and msg == 'quit': # if so, exists the loop
break
# "Processes" (or in our case, prints) the queue item
print "I'm a thread, and I received %s!!" % msg # Always be friendly!
print 'Bye byes!'def Producer():
# Queue is used to share items between
# the threads.
queue = Queue.Queue() # Create an instance of the worker
worker = Consumer(queue) # start calls the internal run() method to
# kick off the thread
worker.start()
# variable to keep track of when we started
start_time = time.time()
# While under 5 seconds..
while time.time() - start_time < 5:
# "Produce" a piece of work and stick it in
# the queue for the Consumer to process
queue.put('something at %s' % time.time()) # Sleep a bit just to avoid an absurd number of messages
time.sleep(1) # This the "poison pill" method of killing a thread.
queue.put('quit') # wait for the thread to close down
worker.join()if __name__ == '__main__':
Producer()
哈,看起来有些像 Java 不是吗?
我并不是说使用生产者/消费者模型处理多线程/多进程任务是错误的(事实上,这一模型自有其用武之地)。只是,处理日常脚本任务时我们可以使用更有效率的模型。
问题在于…
首先,你需要一个样板类;
其次,你需要一个队列来传递对象;
而且,你还需要在通道两端都构建相应的方法来协助其工作(如果需想要进行双向通信或是保存结果还需要再引入一个队列)。
worker 越多,问题越多
按照这一思路,你现在需要一个 worker 线程的线程池。下面是一篇 IBM 经典教程中的例子——在进行网页检索时通过多线程进行加速。
#Example2.py'''
A more realistic thread pool example
'''import time
import threading
import Queue
import urllib2
class Consumer(threading.Thread):
def __init__(self, queue):
threading.Thread.__init__(self)
self._queue = queue
def run(self):
while True:
content = self._queue.get()
if isinstance(content, str) and content == 'quit': break
response = urllib2.urlopen(content) print 'Bye byes!'def Producer():
urls = [ 'http', 'httcom'
'ala.org', 'hle***m'
# etc..
]
queue = Queue.Queue()
worker_threads = build_worker_pool(queue, 4)
start_time = time.time() # Add the urls to process
for url in urls:
queue.put(url)
# Add the poison pillv
for worker in worker_threads:
queue.put('quit') for worker in worker_threads:
worker.join() print 'Done! Time taken: {}'.format(time.time() - start_time)def build_worker_pool(queue, size):
workers = [] for _ in range(size):
worker = Consumer(queue)
worker.start()
workers.append(worker) return workersif __name__ == '__main__':
Producer()
这段代码能正确的运行,但仔细看看我们需要做些什么:构造不同的方法、追踪一系列的线程,还有为了解决恼人的死锁问题,我们需要进行一系列的 join 操作。这还只是开始……
至此我们回顾了经典的多线程教程,多少有些空洞不是吗?样板化而且易出错,这样事倍功半的风格显然不那么适合日常使用,好在我们还有更好的方法。
何不试试 map
map 这一小巧精致的函数是简捷实现 Python 程序并行化的关键。map 源于 Lisp 这类函数式编程语言。它可以通过一个序列实现两个函数之间的映射。
urls = ['ho***m', 'htdit***m']
results = map(urllib2.urlopen, urls)
上面的这两行代码将 urls 这一序列中的每个元素作为参数传递到 urlopen 方法中,并将所有结果保存到 results 这一列表中。其结果大致相当于:
results = []for url in urls:
results.append(urllib2.urlopen(url))
map 函数一手包办了序列操作、参数传递和结果保存等一系列的操作。
为什么这很重要呢?这是因为借助正确的库,map 可以轻松实现并行化操作。
在 Python 中有个两个库包含了 map 函数: multiprocessing 和它鲜为人知的子库 multiprocessing.dummy.
这里多扯两句: multiprocessing.dummy? mltiprocessing 库的线程版**?这是虾米?即便在 multiprocessing 库的官方文档里关于这一子库也只有一句相关描述。而这句描述译**话基本就是说:"嘛,有这么个东西,你知道就成."相信我,这个库被严重低估了!
dummy 是 multiprocessing 模块的完整**,唯一的不同在于 multiprocessing 作用于进程,而 dummy 模块作用于线程(因此也包括了 Python 所有常见的多线程限制)。
所以替换使用这两个库异常容易。你可以针对 IO 密集型任务和 CPU 密集型任务来选择不同的库。2
动手尝试
使用下面的两行代码来引用包含并行化 map 函数的库:
from multiprocessing import Poolfrom multiprocessing.dummy import Pool as ThreadPool
实例化 Pool 对象:
pool = ThreadPool()
这条简单的语句替代了 example2.py 中 build_worker_pool 函数 7 行代码的工作。它生成了一系列的 worker 线程并完成初始化工作、将它们储存在变量中以方便访问。
Pool 对象有一些参数,这里我所需要关注的只是它的第一个参数:processes. 这一参数用于设定线程池中的线程数。其默认值为当前机器 CPU 的核数。
一般来说,执行 CPU 密集型任务时,调用越多的核速度就越快。但是当处理网络密集型任务时,事情有有些难以预计了,通过实验来确定线程池的大小才是明智的。
pool = ThreadPool(4) # Sets the pool size to 4
线程数过多时,切换线程所消耗的时间甚至会超过实际工作时间。对于不同的工作,通过尝试来找到线程池大小的最优值是个不错的主意。
创建好 Pool 对象后,并行化的程序便呼之欲出了。我们来看看改写后的 example2.py
import urllib2
from multiprocessing.dummy import Pool as ThreadPool
urls = [ 'httorg',
'hon.org/about/',
'hnlamp***m/pub/a/python/2003/04/17/metaclasses.html',
# etc..
]
# Make the Pool of workers
pool = ThreadPool(4)
# Open the urls in their own threads
# and return the results
results = pool.map(urllib2.urlopen, urls)
#close the pool and wait for the work to finish
pool.close()
pool.join()
实际起作用的代码只有 4 行,其中只有一行是关键的。map 函数轻而易举的取代了前文中超过 40 行的例子。为了更有趣一些,我统计了不同方法、不同线程池大小的耗时情况。
# results = [] # for url in urls:# result = urllib2.urlopen(url)# results.append(result)# # ------- VERSUS ------- # # # ------- 4 Pool ------- # # pool = ThreadPool(4) # results = pool.map(urllib2.urlopen, urls)# # ------- 8 Pool ------- # # pool = ThreadPool(8) # results = pool.map(urllib2.urlopen, urls)# # ------- 13 Pool ------- # # pool = ThreadPool(13) # results = pool.map(urllib2.urlopen, urls)
结果:
# Single thread: 14.4 Seconds # 4 Pool: 3.1 Seconds# 8 Pool: 1.4 Seconds# 13 Pool: 1.3 Seconds
很棒的结果不是吗?这一结果也说明了为什么要通过实验来确定线程池的大小。在我的机器上当线程池大小大于 9 带来的收益就十分有限了。
对于有一定编程经验的人来说,python相对好学些。
而其他人,则要看一点毅力和天赋了,因为学以致用,最终用python达到你的学习目的,才算有价值。若只是单纯的学学,开始也不算太难,但深入还是有一定难度的,特别是一些大项目。相比之下,python的一大好处,就是各类现成的实用库,几行代码就可以实现一个小目标。
python,将来还是蛮有用的,就连地产大佬潘石屹,都开始学python了(虽然不明白他的意图)。
人生苦短,我用python!
简单一个爬虫,可以用urllib,requests,beautifulsoup可以实现。 比如爬百度首页, import requestsr = requests.get("http://www.baidu.com")# 访问百度主页r.encoding = 'utf-8' 更改编码为utf-8print (r.text[:1000]) # 打印网页内容,这里控制打印出来的字符数量,以免idle假死。以上是简单的爬虫,难度往上就是,采集多页内容,指定采集一些url结构的内容,登录采集(直线——验证码,post get),采集javascript生成的内容,采集雪球网页。等等。 验证码这部分,现在比较多的是极验,也就是拉动拼图到一定位置,然后放开鼠标,拼合拼图的那种验证码。这种验证码目前也没几个人能**。
相对于人工智能、数据分析、深度学习来讲,Python爬虫还是比较简单的。想要从事爬虫工作,需要掌握以下知识: 学习Python基础知识并实现基本的爬虫过程 一般获取数据的过程都是按照 发送请求-获得页面反馈-解析并且存储数据 这三个流程来实现的。这个过程其实就是模拟了一个人工浏览网页的过程。 Python中爬虫相关的包很多:urllib、requests、bs4、scrapy、pyspider 等,我们可以按照requests 负责连接网站,返回网页,Xpath 用于解析网页,便于抽取数据。 2.了解非结构化数据的存储 爬虫抓取的数据结构复杂 传统的结构化数据库可能并不是特别适合我们使用。我们前期推荐使用MongoDB 就可以。 3. 掌握一些常用的反爬虫技巧 使用代理IP池、抓包、验证码的OCR处理等处理方式既可以解决大部分网站的反爬虫策略。 4.了解分布式存储 分布式这个东西,听起来很恐怖,但其实就是利用多线程的原理让多个爬虫同时工作,需要你掌握 Scrapy + MongoDB + Redis 这三种工具就可以了。
相对于人工智能、数据分析、深度学习来讲,Python爬虫还是比较简单的。想要从事爬虫工作,需要掌握以下知识: 学习Python基础知识并实现基本的爬虫过程 一般获取数据的过程都是按照 发送请求-获得页面反馈-解析并且存储数据 这三个流程来实现的。这个过程其实就是模拟了一个人工浏览网页的过程。 Python中爬虫相关的包很多:urllib、requests、bs4、scrapy、pyspider 等,我们可以按照requests 负责连接网站,返回网页,Xpath 用于解析网页,便于抽取数据。 2.了解非结构化数据的存储 爬虫抓取的数据结构复杂 传统的结构化数据库可能并不是特别适合我们使用。我们前期推荐使用MongoDB 就可以。 3. 掌握一些常用的反爬虫技巧 使用代理IP池、抓包、验证码的OCR处理等处理方式既可以解决大部分网站的反爬虫策略。 4.了解分布式存储 分布式这个东西,听起来很恐怖,但其实就是利用多线程的原理让多个爬虫同时工作,需要你掌握 Scrapy + MongoDB + Redis 这三种工具就可以了。
对于有一定编程经验的人来说,python相对好学些。
而其他人,则要看一点毅力和天赋了,因为学以致用,最终用python达到你的学习目的,才算有价值。若只是单纯的学学,开始也不算太难,但深入还是有一定难度的,特别是一些大项目。相比之下,python的一大好处,就是各类现成的实用库,几行代码就可以实现一个小目标。
python,将来还是蛮有用的,就连地产大佬潘石屹,都开始学python了(虽然不明白他的意图)。
人生苦短,我用python!
开发网络爬虫应该选择Nutch、Crawler4j、WebMagic、scrapy、WebCollector还是其他的?这里按照我的经验随便扯淡一下:上面说的爬虫,基本可以分3类:1.分布式爬虫:Nutch
2.JAVA单机爬虫:Crawler4j、WebMagic、WebCollector
3. 非JAVA单机爬虫:scrapy
第一类:分布式爬虫
爬虫使用分布式,主要是解决两个问题:
1)海量URL管理
2)网速
现在比较流行的分布式爬虫,是Apache的Nutch。但是对于大多数用户来说,Nutch是这几类爬虫里,最不好的选择,理由如下:
1)Nutch是为搜索引擎设计的爬虫,大多数用户是需要一个做精准数据爬取(精抽取)的爬虫。Nutch运行的一套流程里,有三分之二是为了搜索引擎而设计的。对精抽取没有太大的意义。也就是说,用Nutch做数据抽取,会浪费很多的时间在不必要的计算上。而且如果你试图通过对Nutch进行二次开发,来使得它适用于精抽取的业务,基本上就要破坏Nutch的框架,把Nutch改的面目全非,有修改Nutch的能力,真的不如自己重新写一个分布式爬虫框架了。
2)Nutch依赖hadoop运行,hadoop本身会消耗很多的时间。如果集群机器数量较少,爬取速度反而不如单机爬虫快。
3)Nutch虽然有一套插件机制,而且作为亮点宣传。可以看到一些开源的Nutch插件,提供精抽取的功能。但是开发过Nutch插件的人都知道,Nutch的插件系统有多蹩脚。利用反射的机制来加载和调用插件,使得程序的编写和调试都变得异常困难,更别说在上面开发一套复杂的精抽取系统了。而且Nutch并没有为精抽取提供相应的插件挂载点。Nutch的插件有只有五六个挂载点,而这五六个挂载点都是为了搜索引擎服务的,并没有为精抽取提供挂载点。大多数Nutch的精抽取插件,都是挂载在“页面解析”(parser)这个挂载点的,这个挂载点其实是为了解析链接(为后续爬取提供URL),以及为搜索引擎提供一些易抽取的网页信息(网页的meta信息、text文本)。
4)用Nutch进行爬虫的二次开发,爬虫的编写和调试所需的时间,往往是单机爬虫所需的十倍时间不止。了解Nutch源码的学习成本很高,何况是要让一个团队的人都读懂Nutch源码。调试过程中会出现除程序本身之外的各种问题(hadoop的问题、hbase的问题)。
5)很多人说Nutch2有gora,可以持久化数据到avro文件、hbase、mysql等。很多人其实理解错了,这里说的持久化数据,是指将URL信息(URL管理所需要的数据)存放到avro、hbase、mysql。并不是你要抽取的结构化数据。其实对大多数人来说,URL信息存在哪里无所谓。
6)Nutch2的版本目前并不适合开发。官方现在稳定的Nutch版本是nutch2.2.1,但是这个版本绑定了gora-0.3。如果想用hbase配合nutch(大多数人用nutch2就是为了用hbase),只能使用0.90版本左右的hbase,相应的就要将hadoop版本降到hadoop 0.2左右。而且nutch2的官方教程比较有误导作用,Nutch2的教程有两个,分别是Nutch1.x和Nutch2.x,这个Nutch2.x官网上写的是可以支持到hbase 0.94。但是实际上,这个Nutch2.x的意思是Nutch2.3之前、Nutch2.2.1之后的一个版本,这个版本在官方的SVN中不断更新。而且非常不稳定(一直在修改)。
所以,如果你不是要做搜索引擎,尽量不要选择Nutch作为爬虫。有些团队就喜欢跟风,非要选择Nutch来开发精抽取的爬虫,其实是冲着Nutch的名气(Nutch作者是Doug Cutting),当然最后的结果往往是项目延期完成。
如果你是要做搜索引擎,Nutch1.x是一个非常好的选择。Nutch1.x和solr或者es配合,就可以构成一套非常强大的搜索引擎了。如果非要用Nutch2的话,建议等到Nutch2.3发布再看。目前的Nutch2是一个非常不稳定的版本。
第二类:JAVA单机爬虫
这里把JAVA爬虫单独分为一类,是因为JAVA在网络爬虫这块的生态圈是非常完善的。相关的资料也是最全的。这里可能有争议,我只是随便扯淡。
其实开源网络爬虫(框架)的开发非常简单,难问题和复杂的问题都被以前的人解决了(比如DOM树解析和定位、字符集检测、海量URL去重),可以说是毫无技术含量。包括Nutch,其实Nutch的技术难点是开发hadoop,本身代码非常简单。网络爬虫从某种意义来说,类似遍历本机的文件,查找文件中的信息。没有任何难度可言。之所以选择开源爬虫框架,就是为了省事。比如爬虫的URL管理、线程池之类的模块,谁都能做,但是要做稳定也是需要一段时间的调试和修改的。
对于爬虫的功能来说。用户比较关心的问题往往是:
1)爬虫支持多线程么、爬虫能用代理么、爬虫会爬取重复数据么、爬虫能爬取JS生成的信息么?
不支持多线程、不支持代理、不能过滤重复URL的,那都不叫开源爬虫,那叫循环执行http请求。
能不能爬js生成的信息和爬虫本身没有太大关系。爬虫主要是负责遍历网站和下载页面。爬js生成的信息和网页信息抽取模块有关,往往需要通过模拟浏览器(htmlunit,selenium)来完成。这些模拟浏览器,往往需要耗费很多的时间来处理一个页面。所以一种策略就是,使用这些爬虫来遍历网站,遇到需要解析的页面,就将网页的相关信息提交给模拟浏览器,来完成JS生成信息的抽取。
2)爬虫可以爬取ajax信息么?
网页上有一些异步加载的数据,爬取这些数据有两种方法:使用模拟浏览器(问题1中描述过了),或者分析ajax的http请求,自己生成ajax请求的url,获取返回的数据。如果是自己生成ajax请求,使用开源爬虫的意义在哪里?其实是要用开源爬虫的线程池和URL管理功能(比如断点爬取)。
如果我已经可以生成我所需要的ajax请求(列表),如何用这些爬虫来对这些请求进行爬取?
爬虫往往都是设计成广度遍历或者深度遍历的模式,去遍历静态或者动态页面。爬取ajax信息属于deep web(深网)的范畴,虽然大多数爬虫都不直接支持。但是也可以通过一些方法来完成。比如WebCollector使用广度遍历来遍历网站。爬虫的第一轮爬取就是爬取种子集合(seeds)中的所有url。简单来说,就是将生成的ajax请求作为种子,放入爬虫。用爬虫对这些种子,进行深度为1的广度遍历(默认就是广度遍历)。
3)爬虫怎么爬取要**的网站?
这些开源爬虫都支持在爬取时指定cookies,模拟**主要是靠cookies。至于cookies怎么获取,不是爬虫管的事情。你可以手动获取、用http请求模拟**或者用模拟浏览器自动**获取cookie。
4)爬虫怎么抽取网页的信息?
开源爬虫一般都会集成网页抽取工具。主要支持两种规范:CSS SELECTOR和XPATH。至于哪个好,这里不评价。
5)爬虫怎么保存网页的信息?
有一些爬虫,自带一个模块负责持久化。比如webmagic,有一个模块叫pipeline。通过简单地配置,可以将爬虫抽取到的信息,持久化到文件、数据库等。还有一些爬虫,并没有直接给用户提供数据持久化的模块。比如crawler4j和webcollector。让用户自己在网页处理模块中添加提交数据库的操作。至于使用pipeline这种模块好不好,就和操作数据库使用ORM好不好这个问题类似,取决于你的业务。
6)爬虫被网站封了怎么办?
爬虫被网站封了,一般用多代理(随机代理)就可以解决。但是这些开源爬虫一般没有直接支持随机代理的切换。所以用户往往都需要自己将获取的代理,放到一个全局数组中,自己写一个代理随机获取(从数组中)的代码。
7)网页可以调用爬虫么?
爬虫的调用是在Web的服务端调用的,平时怎么用就怎么用,这些爬虫都可以使用。
8)爬虫速度怎么样?
单机开源爬虫的速度,基本都可以讲本机的网速用到极限。爬虫的速度慢,往往是因为用户把线程数开少了、网速慢,或者在数据持久化时,和数据库的交互速度慢。而这些东西,往往都是用户的机器和二次开发的代码决定的。这些开源爬虫的速度,都很可以。
9)明明代码写对了,爬不到数据,是不是爬虫有问题,换个爬虫能解决么?
如果代码写对了,又爬不到数据,换其他爬虫也是一样爬不到。遇到这种情况,要么是网站把你封了,要么是你爬的数据是javascript生成的。爬不到数据通过换爬虫是不能解决的。
10)哪个爬虫可以判断网站是否爬完、那个爬虫可以根据主题进行爬取?
爬虫无法判断网站是否爬完,只能尽可能覆盖。
至于根据主题爬取,爬虫之后把内容爬下来才知道是什么主题。所以一般都是整个爬下来,然后再去筛选内容。如果嫌爬的太泛,可以通过限制URL正则等方式,来缩小一下范围。
11)哪个爬虫的设计模式和构架比较好?
设计模式纯属扯淡。说软件设计模式好的,都是软件开发完,然后总结出几个设计模式。设计模式对软件开发没有指导性作用。用设计模式来设计爬虫,只会使得爬虫的设计更加臃肿。
至于构架,开源爬虫目前主要是细节的数据结构的设计,比如爬取线程池、任务队列,这些大家都能控制好。爬虫的业务太简单,谈不上什么构架。
所以对于JAVA开源爬虫,我觉得,随便找一个用的顺手的就可以。如果业务复杂,拿哪个爬虫来,都是要经过复杂的二次开发,才可以满足需求。
第三类:非JAVA单机爬虫
在非JAVA语言编写的爬虫中,有很多优秀的爬虫。这里单独提取出来作为一类,并不是针对爬虫本身的质量进行讨论,而是针对larbin、scrapy这类爬虫,对开发成本的影响。
先说python爬虫,python可以用30行代码,完成JAVA 50行代码干的任务。python写代码的确快,但是在调试代码的阶段,python代码的调试往往会耗费远远多于编码阶段省下的时间。使用python开发,要保证程序的正确性和稳定性,就需要写更多的测试模块。当然如果爬取规模不大、爬取业务不复杂,使用scrapy这种爬虫也是蛮不错的,可以轻松完成爬取任务。
对于C++爬虫来说,学习成本会比较大。而且不能只计算一个人的学习成本,如果软件需要团队开发或者交接,那就是很多人的学习成本了。软件的调试也不是那么容易。
还有一些ruby、php的爬虫,这里不多评价。的确有一些非常小型的数据采集任务,用ruby或者php很方便。但是选择这些语言的开源爬虫,一方面要调研一下相关的生态圈,还有就是,这些开源爬虫可能会出一些你搜不到的BUG(用的人少、资料也少)
End.
你可以用前嗅爬虫采集豆瓣的影评,我之前用的,还可以过滤只采集评分在6分以上的所有影评,非常强大,而且他们软件跟数据库对接,采集完数据后,直接入库,导出excel表。很省心。
爬虫是互联网上最常见的一种东西了吧。
爬虫这东西每天都在网上爬大量的信息,各大搜索引擎厂商每天都有上百万的爬虫在网络上活动,这些爬虫的作用就是给搜索引擎采集互联网上最新的内容,采集来的内容经过分类、加工之后,进入搜索引擎的索引。这是爬虫最常见的应用。
关于搜索引擎的理论非常多,应该已经形成系统的理论和方法了。这里不再多追求搜索引擎的细节,只来看看爬虫如何爬有效的信息。
ps. 这个博客已经很久没有更新了。现在时间越来越少,平时鲜有时间来更新博客了。
最近某人发现,python其实是一种很适合写爬虫的语言,而且python越用越顺手。现在若是有人问我“c++和c#学哪一个?“之类的问题的时候,我一定会说,学python吧,因为生命短暂,你应该学习python。
所谓爬虫,就是把网页的html下载下来,然后从里面提取出来有用的信息,这些有用的信息一般就是正文,图片,链接一类的信息。
针对特定网站的爬虫就更好写了,用正则表达式,把网页里的链接信息找到,然后找到需要的信息,保存在本地,然后进入下一个链接重复上一次的过程。
下面的脚本演示如何从加菲猫的官网上把从1978年至今的所有漫画全部下载下来
import os,urllib,urllib2,re
hosts = "http://**********"
#initpos = "/mobile/garfield/1978/06/19"
initpos ="/mobile/garfield/1979/08/08"
pname = re***mpile('''.+?(.*?)''')
pcomic = re***mpile('''''')
pnext = re***mpile('''''')
def getpage(url):
print url
req = urllib2.Request(url)
req.add_header("User-Agent","Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:21.0) Gecko/20100101 Firefox/21.0")
req.add_header("If-None-Match","c1858c2845ca9501136ca83d624f8d4d")
u = urllib2.urlopen(req).read()
return u
def getnextpos(content,patten):
r = patten.findall(content)
for x in r:
print 'find next: ',x
return x
def savecomic(content,patten):
r = patten.findall(content)
print 'find commic:',r
r2 = pname.findall(content)
print 'find name:',r2
urlcomic = r[0]
u = urllib.urlopen(urlcomic).read()
name = r2[0].replace(' ','').split(',')
year = name[-1]
day = name[-2]
filename = 'test.jpg'
if not os.path.exists(year):
os.makedirs(year)
# is gif file ,the name the file as gif
if ((u[0] is 'G') and (u[1] is 'I') and (u[2] is 'F')):
filename = year+day+'.gif'
else:
filename = year+day+'.jpg'
f = file(year+"/"+filename,"wb+")
f.write(u)
f.close()
def main():
url = hosts+initpos
while(True):
c = getpage(url)
savecomic(c,pcomic)
u = getnextpos(c,pnext)
if u is None:
break
else:
url = hosts+u
if __name__ == '__main__':
main()
本文由宠物迷 百科常识栏目发布,非常欢迎各位朋友分享到个人朋友圈,但转载请说明文章出处“有没有易懂的 Python 多线程爬虫代码”
上一篇
洪山区与武昌区分界线?
下一篇
狗狗就餐完后碗具要不要清洁?