'''
一个线程在使用这个共享的时候,其他线程必须等待他结束
通过"锁"实现,作用就是防止多个线程使用这片内存空间
进程:程序的一次执行
线程: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. Android NDK 环境变量配置

    NDK_ROOT = C:\__S_D_K__\AndroidNDK\android-ndk-r20 在path 中加入  %NDK_ROOT% 我的路径在C盘 //个别的程序可能需要 NDK_ROO ...

  2. BZOJ 3626: [LNOI2014]LCA(树剖+差分+线段树)

    传送门 解题思路 比较有意思的一道题.首先要把求\(\sum\limits_{i=l}^r dep[lca(i,z)]\)这个公式变一下.就是考虑每一个点的贡献,做出贡献的点一定在\(z\)到根节点的 ...

  3. APIO 2017 商旅 洛谷3778

    Description 在广阔的澳大利亚内陆地区长途跋涉后,你孤身一人带着一个背包来到了科巴.你被这个城市发达而美丽的市场所 深深吸引,决定定居于此,做一个商人.科巴有个集市,集市用从1到N的整数编号 ...

  4. 双目立体匹配经典算法之Semi-Global Matching(SGM)概述:视差计算、视差优化

    文章目录 视差计算 视差优化 剔除错误匹配 提高视差精度 抑制噪声 视差计算   在SGM算法中,视差计算采用赢家通吃(WTA)算法,每个像素选择最小聚合代价值所对应的视差值作为最终视差,视差计算的结 ...

  5. NX二次开发-获取坐标系信息UF_CSYS_ask_csys_info

    NX9+VS2012 #include <uf.h> #include <uf_csys.h> UF_initialize(); //获取WCS标识 tag_t WcsId = ...

  6. NX二次开发-UFUN设置对象线型UF_OBJ_set_font

    #include <uf.h> #include <uf_modl.h> #include <uf_obj.h> UF_initialize(); //创建块 UF ...

  7. spring 配置bean以及配置依赖 (2)

    目录 一.使用ref引用其他对象 二.通过有参构造器创建对象 1 通过index精确定位参数顺序 三.引用bean 1 使用内部bean 2 使用list,set 3 声明集合类型 四.其他 1 使用 ...

  8. codeforces round#524 D - Olya and magical square /// 大概算是数学规律题?

    题目大意: t 个测试用例  (1≤t≤103) 给定n k  (1≤n≤10^9,1≤k≤10^18) 表示有一个边长为2^n的正方形格子 每次操作只能将一个格子切割为左上左下右上右下的四等分格子 ...

  9. css元素垂直居中

    一.碎碎念:啊啊啊,原谅我只能起一个酱紫微大众微俗气的标题,因为实在没有什么能比这样表达的更清楚直观了呢! 二.没有知识储备,直接上示例: 1.思路:给父元素添加display: table属性:给子 ...

  10. spring MVC 全局的异常处理

    1.使用SimpleMappingExceptionResolver实现异常处理 在Spring的配置文件applicationContext.xml中增加以下内容: <bean class=& ...