多线程爬虫,主要是玩队列,队列玩明白了,多线程自然也就起来了。
#导入各种包
import threading
import queue
impot json
from lxml import ertee
定义爬取类,需要继承多线程:
class down_spider(Threading.Thread):
def __intit__(self,urlQ,dataQ):
super(down_spider,self).__init__()
self.urlQ = urlQ
self.dataQ = dataQ
def run(self):#重写run方法
self.down()
def down(self):
while True:#记住这里要写一个循环,不然一个线程只会取一次url就不干活了
if self.urlQ.empty():
break
url = self.urlQ.get()
'''
然后这里就写怎么爬取,设置代理之类的.....
假设是这样:response = requests.get(url)
'''
self.dataQ.put(response.text)#text返回一个string,content返回一个字节流
self.dataQ.task_done()#通知任务队列,这个任务完成了
class parser_handle(Threading.Thread):
def __intit__(self,dataQ,lock,file):
super(parser_handle,self).__init__()
self.dataQ= dataQ
self.lock = lock
self.file = file#结果保存到文件里把,文件要从主线程那里创建
def run(self):
while True:
if self.dataQ.empty():
break
text = self.dataQ.get()
html = etree.HTML(text)
'''
然后这里写解析规则
假如是这样:title = html.xpath('//title')
item = {
'title':title,
}
'''
with self.lock:
self.file.wrtie(json.dupms(item,ensure_ascii=False))
定义两个队列,一个用来存url,一个用来存down下来的页面
urlQ= queue.Queue()#默认是先进先出
dataQ = queue.Queue()
lock = threading.RLock()
file = io.open('result.txt','a',encoding='utf-8')
#先把urlQ里的url搞出来
#自己找出规律,存储到urlQ里面
'''
假设是这样:
urlQ = queue.Queue()
for i in range(1,20):
full_url = 'https://www.啊哈啊哈.com/' + str(i) + '/'
urlQ.put(full_url)
'''
#接下来搞五个线程去爬取
thread_down = []
for i in range(5):
t = down_spider(urlQ,dataQ)
t.start()
thread_down.append(t)
#在搞五个线程来解析加存储
thread_parser = []
for i in range(5):
t = parser_handle(dataQ,lock,file)
t.start()
thread_down.append(t)
#jion一下,让主线程等着我们,都搞完了再退
for t in thread_down:
t.join()
for t in thread_parser:
t.join()
file.close()
print('史上最简陋的多线程爬虫结束了')
多线程爬虫,首先要把队列搞明白,懂得队列的存取,并且需要知道自己需要的是哪种类型的队列,是先进先出,还是先进后出,还是优先级。然后就是用类来写的话,重写run方法,一定要记得while True,并且要给他一个出口。再然后就是锁了, 其实锁这块我不明白,只知道一点,写文件的时候需要加锁,不然大家都去写,不就乱了嘛。
接下来需要搞一下协程,搜集日志,异常处理,代理的使用。
这篇博客看了很有收获,讲的是线程爬虫、协程爬虫https://blog.csdn.net/xinkexueguanli/article/details/52552107