上文在有提到过 反爬虫
的问题,禁止访问只是 反爬虫
的其中一种策略,下面来讲另外一种反爬虫策略 抓取时间
。
假设一个爬虫程序抓取网页的速度和正常用浏览器复制的速度一样,那么这个爬虫程序无疑是失败的,假设要抓取的信息很多,一个爬虫程序跑几天都没跑完,那么应该要想到提高程序的效率。例如一个新闻公司需要爬虫工程师去抓取实时的新闻资讯,这样就会对爬虫的速度有很大的要求,要保证 实时 ,所以爬虫要抓取得快,而不是现在更新出新的新闻了,而你的程序还没抓完上个小时的新闻,因此本文要从提高爬虫的效率来写,主要介绍 2
个多线程的库:
threading
concurrent.futures
在前文中作者抓取自己网页 首页 的图片,在程序中是以一个 for
来以此下载图片的,每张图片大约 100kb-200kb
,但是作者的带宽是能达到 1M/s
,假设能让这11张图片同时下载,那么将节约一部分时间出来,现在介绍这2个多线程库的用法。
threading
是官方库,无需自己安装,直接就可以调用。本文将下载图片的代码封装成一个 function
,再将图片的 imgurl
传入到这个 function
里面,用 threading
执行 function
就会自动变成多线程了。
调用的方式也很简单:
import threading
# 创建线程池
threadpool = []
# 定义线程
th = threading.Thread(target=fun_name, args=(args))
# 将线程加入线程池
threadpool.append(th)
# 开始线程
for th in threadpool:
th.start()
# 等待所有线程运行完毕
for th in threadpool:
th.join()
这里只要将下载图片的代码改写成函数 fun_name
,传入的参数为 img_src
就行。例如函数可以写成:
def downloadimg(imgurl,imgname):
saveimg = open("E:/" + str(imgname) + ".jpg", 'wb')
saveimg.write(urllib.request.urlopen(imgurl).read())
saveimg.close()
最后根据前面学到的方法,将所有图片的 img_url
定义到线程里面去,即:
for imgurl in imgurls:
th = threading.Thread(target=downloadimg, args=(imgurl,imgname))
threadpool.append(th)
最后开启线程,这样就可以让所有的图片,也就是 11
张图片一起下载:
concurrent.futures
其实也是基于 threading
封装的官方库,这个库更加简单粗暴,可以随意定义线程的数量,只要自己的机器承受得住,那么可以开随意多的线程来并发执行抓取任务,这也是爬虫必须了解的一个库。
concurrent.futures
调用的方式也很简单:
from concurrent.futures import ThreadPoolExecutor
# 定义线程的最大数量为11,因为一共是11张图片
pool=ThreadPoolExecutor(max_workers=11)
# 将下载图片的任务加入线程
for imgurl in imgurls:
newimgurl = "http://www.tybai.com/" + imgurl[1].replace("\\", "")
pool.submit(downloadimg,newimgurl,imgname)
用 两种多线程 抓取 http://www.tybai.com/topic 里面文章的详情页,将其 html 下载到本地