'''
一个线程在使用这个共享的时候,其他线程必须等待他结束
通过"锁"实现,作用就是防止多个线程使用这片内存空间
进程:程序的一次执行
线程:cpu运算的基本调度单位
多线程:大量密集I/O处理,在等待响应的时候,其他线程去工作
多进程:大量的密集并行计算
scrapy:异步网络框架(很多协程在处理)
页码队列--线程取页码爬取(采集线程--网络IO)--数据队列(得到的响应)--线程解析网页(解析线程磁盘IO)--解析后的数据存储
'''
# 请求
import requests
# 队列
from multiprocessing import Queue
# 线程
from threading import Thread
import threading
# 解析
from lxml import etree
# 存储
import json
import time class ThreadCrawl(Thread):
def __init__(self, threadName, pageQueue, dataQueue):
# 调用父类的初始化方法
super(ThreadCrawl, self).__init__()
self.threadName = threadName
self.pageQueue = pageQueue
self.dataQueue = dataQueue
self.headers = {"User-Agent":"Mozilla/5.0(Windows NT 10.0;WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.170 Safari/537.36"} # thread.start()会执行run方法
def run(self):
print("启动"+self.threadName)
while not CRAWL_EXIT:
try:
# 从页码队列取出一个数字,
# 可选参数block(默认Ture)
# 1.队列为空,block为Ture,会进入阻塞状态,直到有新的值进入队列
# 2.如果队列为空.block为False,会弹出Queue.empty()出错
page = self.pageQueue.get(False)
url = "https://www.qiushibaike.com/text/page/" + str(page) + "/"
content = requests.get(url,headers=self.headers).text
#调用数据队列,将源码放进去
self.dataQueue.put(content)
except:
pass
print("结束"+self.threadName) class ThreadParse(Thread):
def __init__(self,threadName,dataQueue,filename,lock):
super(ThreadParse,self).__init__()
self.threadName = threadName
self.dataQueue = dataQueue
self.filename = filename
self.lock = lock def run(self):
while not PARSE_EXIT:
try:
html = self.dataQueue.get(False)
self.parse(html)
except:
pass def parse(self,html):
html = etree.HTML(html)
print(html) # with 后面有两个必须执行的操作:__enter__ 和 _exit__
# 不管里面的操作结果如何,都会执行打开、关闭
# 打开锁、处理内容、释放锁
with self.lock:
# 写入存储的解析后的数据
self.filename.write(json.dumps(html, ensure_ascii=False).encode("utf-8") + "\n") CRAWL_EXIT = False
PARSE_EXIT = False def main():
# 页码队列,可以存储20个值
pageQueue = Queue(20)
# 放入1-10数字,先进先出
for i in range(1, 21):
pageQueue.put(i) # 数据队列,HTML源码,不写参数,默认无限
dataQueue = Queue() # 创建锁
lock = threading.Lock() # 采集线程名字
crawlList = ["采集线程1号", "采集线程2号", "采集线程3号"] # 存储采集线程
thread_crawl = []
for threadName in crawlList:
# 写一个
thread = ThreadCrawl(threadName, pageQueue, dataQueue)
thread.start()
thread_crawl.append(thread) filename = open("duanzi.json","a")
#解析线程名字
parseList = ["解析线程1号","解析线程2号","解析线程3号"]
threadparse = []
for threadName in parseList:
thread = ThreadParse(threadName,dataQueue,filename,lock)
thread.start()
threadparse.append(thread) #如果队列不为空,一直在这等待
while not pageQueue.empty():
pass
#如果队列为空,CRAWL_EXIT = True 退出
global CRAWL_EXIT
CRAWL_EXIT = True #加阻塞,线程做完才能运行主线程
for thread in thread_crawl:
thread.join()
print(thread) while not dataQueue.empty():
pass global PARSE_EXIT
PARSE_EXIT = True for thread in threadparse:
thread.join()
print(thread) with lock:
# 关闭文件
filename.close()
print("谢谢使用") if __name__ == '__main__':
main()

  

<随便写> 多线程的例子的更多相关文章

  1. python两段多线程的例子

    记录瞬间 =====================其一===================== # coding:UTF-8 import os import threading from tim ...

  2. C#多线程简单例子讲解

    C#多线程简单例子讲解 标签: 多线程c#threadobjectcallbacktimer 分类: C#(7) 转载网址:http://www.knowsky.com/540518.html .NE ...

  3. Peer模式的多线程程序例子

    Peer模式的多线程程序例子 程序的模型大概是这样的.有一个master(),用来分发任务.有N个多线程的slave用来处理任务. 主程序里可以这样调用: 可以看出,上面这段程序还是依赖于Proces ...

  4. Jquery 随便写些知识点

    针对jQuery随便写些觉得还挺实用的一些东西,也没系统的去理一番,只是想到哪写到哪,写的不完全也请多见谅. jQuery和其他javascript库产生$符号冲突了?$符号想必用jQuery的人都不 ...

  5. 用thinkphp写的一个例子:抓取网站的内容并且保存到本地

    我需要写这么一个例子,到电子课本网下载一本电子书. 电子课本网的电子书,是把书的每一页当成一个图片,然后一本书就是有很多张图片,我需要批量的进行下载图片操作. 下面是代码部分: public func ...

  6. 【转】忙里偷闲写的小例子---读取android根目录下的文件或文件夹

    原文网址:http://www.cnblogs.com/wenjiang/p/3140055.html 最近几天真的是各种意义上的忙,忙着考试,还要忙着课程设计,手上又有外包的项目,另一边学校的项目还 ...

  7. python多线程简单例子

    python多线程简单例子 作者:vpoet mail:vpoet_sir@163.com import thread def childthread(threadid): print "I ...

  8. 忙里偷闲写的小例子---读取android根目录下的文件或文件夹

    最近几天真的是各种意义上的忙,忙着考试,还要忙着课程设计,手上又有外包的项目,另一边学校的项目还要搞,自己的东西还在文档阶段,真的是让人想死啊!! 近半个月来,C#这方面的编码比较多,android和 ...

  9. 再议perl写多线程端口扫描器

    再议perl写多线程端口扫描器 http://blog.csdn.net/sx1989827/article/details/4642179 perl写端口多线程扫描器 http://blog.csd ...

随机推荐

  1. delphi xe10 网络连接

    //当前网络状态(引用 Androidapi.JNI.Network.pas) IsConnected //连接 IsWiFiConnected //Wifi是否连接 IsMobileConnecte ...

  2. CSS案例2(一个简单的新闻网页)

     知识点: 1.一般网页不用纯黑,用淡灰色  3c3c3c 2.text-align: center;  /*  文字水平居中 */ 3.font-weight: normal;  /* 清除加粗效果 ...

  3. 云cassandra 重磅发布dynamodb特性

    云cassandra全新发布dynamodb特性 nosql主力数据库再上新台阶 9月阿里云cassandra产品发布,具体参考阿里云全球首发云Cassandra服务.迄今为止,已有上百大B客户开通了 ...

  4. Android源码的git下载地址

    git clone https://android.googlesource.com/device/common.git    git clone https://android.googlesour ...

  5. 后缀自动机求字典序第k小的串——p3975

    又领悟到了一点新的东西,后缀自动机其实可以分为两个数据结构,一个是后缀树,还有一个是自动机 后缀树用来划分endpos集合,并且维护后缀之间的关系,此时每个结点代表的是一些后缀相同且长度连续的子串 自 ...

  6. 线段树优化dp——牛客多校第一场I(好题)

    和两天做了两道数据结构优化dp的题,套路还是差不多的 题解链接! https://www.cnblogs.com/kls123/p/11221471.html 一些补充 其实这道题的dp[i]维护的不 ...

  7. NOIp2018集训test-9-2(pm)

    其实这套题我爆0了,T1define 写成ddefine编译错误 T2有两个变量爆int 但是我看zwh不在悄悄地改了,我心里还是十分愧疚(没有)的.主要是林巨已经虐我125了要是再虐我200分我大概 ...

  8. nginx按日分割日志

    #!/bin/bash #按日切割nginx日志并压缩,加入crontab每天0:00切割 #作者:fafu_li #时间: source /etc/profile #加载系统环境变量 source ...

  9. 7 Scatter-loading Features

    7.1 About scatter-loading The scatter-loading mechanism enables you to specify the memory map of an ...

  10. Mysql 插入数据,随机事件选择

    在拼写sql的 时候,mysql字段如果需要添加当前时间可以用NOW() 函数 // String sql = ("insert into tablename(content, create ...