那个网站做直播好,中山市网站建设,选择网站建设公司应该注意什么,黄冈做网站的公司哪家好目录多綫程定義簡介原理优点缺点优势代碼框架實現導包打印類爬蟲類構造方法獲取代理設置headers獲取新session獲取源代碼解析網頁解析子頁面保存數據綫程任務得到url啓動多綫程爬蟲總結多綫程
以下定義來自百度百科#xff0c;看看就好沒仔細寫
定義
多线程#xff08;mul…
目录多綫程定義簡介原理优点缺点优势代碼框架實現導包打印類爬蟲類構造方法獲取代理設置headers獲取新session獲取源代碼解析網頁解析子頁面保存數據綫程任務得到url啓動多綫程爬蟲總結多綫程
以下定義來自百度百科看看就好沒仔細寫
定義
多线程multithreading是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程进而提升整体处理性能。具有这种能力的系统包括对称多处理机、多核心处理器以及芯片级多处理或同时多线程处理器。在一个程序中这些独立运行的程序片段叫作“线程”Thread利用它编程的概念就叫作“多线程处理”
簡介
在计算机编程中一个基本的概念就是同时对多个任务加以控制。许多程序设计问题都要求程序能够停下手头的工作改为处理其他一些问题再返回主进程。可以通过多种途径达到这个目的。最开始的时候那些掌握机器低级语言的程序员编写一些“中断服务例程”主进程的暂停是通过硬件级的中断实现的。尽管这是一种有用的方法但编出的程序很难移植由此造成了另一类的代价高昂问题。中断对那些实时性很强的任务来说是很有必要的。但对于其他许多问题只要求将问题划分进入独立运行的程序片断中使整个程序能更迅速地响应用户的请求。
最开始线程只是用于分配单个处理器的处理时间的一种工具。但假如操作系统本身支持多个处理器那么每个线程都可分配给一个不同的处理器真正进入“并行运算”状态。从程序设计语言的角度看多线程操作最有价值的特性之一就是程序员不必关心到底使用了多少个处理器。程序在逻辑意义上被分割为数个线程假如机器本身安装了多个处理器那么程序会运行得更快毋需作出任何特殊的调校。根据前面的论述大家可能感觉线程处理非常简单。但必须注意一个问题共享资源如果有多个线程同时运行而且它们试图访问相同的资源就会遇到一个问题。举个例子来说两个线程不能将信息同时发送给一台打印机。为解决这个问题对那些可共享的资源来说比如打印机它们在使用期间必须进入锁定状态。所以一个线程可将资源锁定在完成了它的任务后再解开释放这个锁使其他线程可以接着使用同样的资源 。
线程是进程中的一部分也是进程的的实际运作单位它也是操作系统中的最小运算调度单位。进程中的一个单一顺序的控制流就是一条线程多个线程可以在一个进程中并发。可以使用多线程技术来提高运行效率。 多线程是为了同步完成多项任务不是为了提高运行效率而是为了提高资源使用效率来提高系统的效率。线程是在同一时间需要完成多项任务的时候实现的
原理
实现多线程是采用一种并发执行机制。
并发执行机制原理简单地说就是把一个处理器划分为若干个短的时间片每个时间片依次轮流地执行处理各个应用程序由于一个时间片很短相对于一个应用程序来说就好像是处理器在为自己单独服务一样从而达到多个应用程序在同时进行的效果。
多线程就是把操作系统中的这种并发执行机制原理运用在一个程序中把一个程序划分为若干个子任务多个子任务并发执行每一个任务就是一个线程。这就是多线程程序。
多线程技术不但可以提高交互式而且能够更加高效、便捷地进行控制。在对多线程应用的时候可以使程序响应速度得到提高从而实现速度化、高效化的特点。另外多线程技术存在的缺点也比较明显需要等待比较长的时间之外还会在一定程度上使程序运行速度降低使工作效率受到一定的影响从而对资源造成了浪费。 具體可以查看操作系統的知識 优点
使用线程可以把占据时间长的程序中的任务放到后台去处理。用户界面可以更加吸引人这样比如用户点击了一个按钮去触发某些事件的处理可以弹出一个进度条来显示处理的进度 。程序的运行速度可能加快。在一些等待的任务实现上如用户输入、文件读写和网络收发数据等线程就比较有用了。在这种情况下可以释放一些珍贵的资源如内存占用等。多线程技术在IOS软件开发中也有举足轻重的作用。
缺点
如果有大量的线程会影响性能因为操作系统需要在它们之间切换更多的线程需要更多的内存空间线程可能会给程序带来更多“bug”因此要小心使用线程的中止需要考虑其对程序运行的影响通常块模型数据是在多个线程间共享的需要防止线程死锁情况的发生。
优势
多进程程序结构和多线程程序结构有很大的不同多线程程序结构相对于多进程程序结构有以下的优势
方便的通信和数据交换 线程间有方便的通信和数据交换机制。对于不同进程来说它们具有独立的数据空间要进行数据的传递只能通过通信的方式进行这种方式不仅费时而且很不方便。线程则不然由于同一进程下的线程之间共享数据空间所以一个线程的数据可以直接为其他线程所用这不仅快捷而且方便。更高效地利用CPU 使用多线程可以加快应用程序的响应。这对图形界面的程序尤其有意义当一个操作耗时很长时整个系统都会等待这个操作此时程序不会响应键盘、鼠标、菜单的操作而使用多线程技术将耗时长的操作置于一个新的线程就可以避免这种尴尬的情况。
同时多线程使多CPU系统更加有效。操作系统会保证当线程数不大于CPU数目时不同的线程运行于不同的CPU上。
代碼框架實現
導包
import random # 隨機
import queue # 隊列
import threading # 綫程
import time # 時間
import requests # http請求
from bs4 import BeautifulSoup # 靚湯解析
import pandas as pd # 數據解析打印類
讓打印的信息有顔色具體可以看我另一篇文章print打印設置字體顔色
class BCOLOR:def __init__(self):self.HEADER \033[95mself.OKBLUE \033[94mself.OKGREEN \033[92mself.ERROR \033[31mself.WARNING \033[93mself.FAIL \033[91mself.ENDC \033[0mself.BOLD \033[1mself.UNDERLINE \033[4mdef yellow(self, s: str):print(self.WARNING s self.ENDC)def blue(self, s: str):print(self.OKBLUE s self.ENDC)def green(self, s: str):print(self.OKGREEN s self.ENDC)def red(self, s: str):print(self.ERROR s self.ENDC)爬蟲類
這個案例啓用5個綫程
構造方法
bprint BCOLOR()
threadNum 5 # 綫程數量
totalNum 0class Spider:def __init__(self):self.urlQueue queue.Queue()self.proxies self.getProxies()urlQueue queue.Queue() 建一個隊列來保存需要爬取的所有ur每個綫程都有這裏取一條利用了隊列先進先出的特點l self.proxies self.getProxies() 得到代理的ip不用代理也行但是速度快不用代理容易被封ip但是使用代理需謹慎
獲取代理 非必須操作看個人選擇 def getProxies(self):pUrl https://api.asdas.com/ip/get # 這個url是假的使用自己買的代理ip接口params {appKey: ,appSecret: }while True:res requests.get(pUrl, headersself.getHeaders(), paramsparams).json()code res.get(code)if code 200:ip res[data][0].get(ip)port res[data][0].get(port)proxies {http: fhttp://{ip}:{port},https: fhttps://{ip}:{port},}print(proxies)return proxies也可以采用自己去爬一些免費代理建立代理詞但是免費不太穩定可能隨時就失效了
設置headers def getHeaders(self):user_agent_list [Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36,Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36,Mozilla/5.0 (Windows NT 10.0; WOW64) Gecko/20100101 Firefox/61.0,Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36,Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.62 Safari/537.36,Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36,Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0),Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.5; en-US; rv:1.9.2.15) Gecko/20110303 Firefox/3.6.15,]headers {User-Agent: random.choice(user_agent_list),}return headers其實隨便設一個ua就好了沒必要隨機拿一個有ua就行了。現在可能都不咋檢查ua了畢竟服務器檢測同一個ip發過來ua能有多不一樣。
如果不設置ua的話原來的ua是python-requests/2.28.1極有可能遇到反爬可能會報錯狀態碼403或者418418就是那個我是一個茶壺有興趣可以去搜一下梗。
這裏大概説一下
这个代码是在1998年作为传统的IETF April Fools‘ jokes被定义的在RFC2324超文本咖啡罐控制协议但是并没有被实际的HTTP服务器实现。RFC指定了这个代码应该是由茶罐返回给速溶咖啡。这当然是一个玩笑甚至连这个RFC的内容都是从歌词里引用过来的。原文如下 The HTCPCP server is a teapot; the resulting entity body may be short and stout. 翻译成中文大概是服务器是个茶壶返回实体短又粗。short and stout 是一句歌词。 “我是一个茶壶我啥也不知道你别找我。” “我是一个茶壶我啥也不知道你找咖啡壶去。” “我是一个茶壶我不是咖啡壶不能当咖啡壶用。” “我是一个茶壶我不是咖啡壶禁止当咖啡壶用。” “我是一个茶壶我不是咖啡壶咖啡煮坏了你自己负责。” “我是一个茶壶暂时还不能当咖啡壶用。” “我是一个茶壶虽然也能煮咖啡但由于某些原因暂时不能煮咖啡。” 可以看一下這個寫的我是一個茶壺
獲取新session def new_session(self):session requests.session()url https://www.scopus.com/while True:try:session.get(urlurl, headersself.getHeaders(), proxiesself.proxies, timeout(3.5, 7))bprint.yellow(snew session)return sessionexcept:self.proxies self.getProxies()bprint.yellow(snetwork error)獲取一個新的session不管出現什麽異常就換代理做的比較水你也可以寫的細緻點
獲取源代碼 def get_html(self, session, url, flag):print(url)print(get_html)while True:try:res session.get(urlurl, headersself.getHeaders(), proxiesself.proxies, timeout(3.5, 7)).text# print(res)if flag in res:return session, ressession self.new_session()bprint.red(serror response)except:self.proxies self.getProxies()bprint.yellow(snetwork timeout)這裏的flag 就是頁面源代碼的一段話如果這段話在res裏證明確實爬到頁面源代碼了那就返回頁面頁面源代碼。這裏寫的簡單點就是不管什麽情況沒爬到就換一個session然後出異常就換代理
解析網頁 def analyze_out(self, session, res, dic: dict) - list:bs解析html:param html::param excelData::return:print(start parse)bs BeautifulSoup(res, html.parser) # 生成靓汤对象解析tbody bs.find_all(class_searchArea) # 搜索区域data_list []for tr in tbody:print(f正在检查第 {tbody.index(tr) 1} 条)# 這裏就是解析網頁可以自己去補充下面給一些示例提示....................th_input tr.find(th).find(input)name th_input.get(name)dic[name] nameflag span classtitleTextin_url fhttps://www.百度.com/in/ # 這裏也是假url需要換你自己的這個就是有一個情況比如頁面内還嵌套一個鏈接你需要去解析子網頁session, res self.get_html(sessionsession, urlin_url, flagflag)dic self.analyze_ins(resres, dicdic) # 這裏就是解析子頁面# print(dic)data_list.append(dic)print(over parse)return data_list這個案例是拿BeautifulSoup解析頁面舉例也可以使用xpathre等
解析子頁面 def analyze_ins(self, res, dic: dict) - dict: 解析子頁面 bs BeautifulSoup(res, html.parser) # 生成靓汤对象解析title bs.find(class_titleText).text # 搜索区域dic[title ] .join(title )return dic這裏使用 ‘’.join(title ) 主要是爲了防止爬不到報錯整個代碼我很少用try捕獲異常
保存數據
def saveMysql(self, dic: dict):這裏自己根據情況自己補充我采用的是保存數據庫想要保存csv還是什麽格式就導入相應的包綫程任務 def thread_work(self, num):global totalNumprint(start)session self.new_session()while True:if self.urlQueue.empty():breakurl self.urlQueue.get()dic {name: ,name: ,name: ,.....需要爬取的數據這裏以一個字典的方式接收先讓每一個建設爲空字符串免得後面報錯}flag title百度一下你就知道/title # 這個flag根據情況自己設置這裏以百度爲例源代碼裏一點有這句話沒有這句話證明是被反爬收到一個js還是假的html之類總之不是我們要的源代碼session, res self.get_html(sessionsession, urlurl, flagflag)dics self.analyze_out(sessionsession, resres, dicdic)with threading.Lock(): 存数据库 for dic in dics:self.saveMysql(dicdic)totalNum 1bprint.green(sfthread: {num} finishNum: {totalNum} data:{dic})設一個死循環如果隊列裏還有需要爬的url就繼續分配給綫程去爬取如果隊列空了就結束
urlQueue.empty()判斷隊列是否爲空返回布爾值urlQueue.get() 在隊列裏取一個url先進先出
得到url def getExcelData(self):print(start readExcel)raw_data pd.read_excel(self.file, header0, keep_default_naFalse) # header0表示第一行是表头就自动去除了raw_list raw_data.values.tolist()url_list []for raw in raw_list:name raw[1]url fhttps://www.百度.com/search/name{LastName} # 這裏依舊是一個假url就是提示一下怎麽構建url根據個人情況修改url_list.append(url)print(over readExcel)return url_list這裏因爲是爬取excel裏的地址所以才這樣根據自己情況構建url隊列即可 這裏用的是pandas來讀取excel也可以使用openpyxlxlwt或者csv等等庫來讀寫excel
pd.read_excel(self.file, header0, keep_default_naFalse)
header0表示第一行是表头就自动去除了keep_default_naFalse假設表格中有一些空行還是空格什麽的不是設置這個則是為nal值設置了這個為空字符串即‘’
raw_data.values.tolist()將DataFrame類型轉換為list列表類型
啓動多綫程爬蟲 def run(self):start time.perf_counter() # 記錄開始時間global threadNumbprint.green(sfprogram starts with {threadNum} threads)url_list self.getExcelData() # 獲取url列表for url in url_list:self.urlQueue.put(url) # 將列表裏的url加入隊列threadList []for i in range(threadNum):t threading.Thread(targetself.thread_work, args(i 1,))threadList.append(t)t.start()for t in threadList:t.join()bprint.green(sprogram finishs)end time.perf_counter()print(Running time: %s Seconds % (end - start)) # 打印執行時間調用這個方法運行這個爬蟲類具體多綫程的使用可以看我另一篇文章demo
總結
這只是寫了一個大概的框架沒有具體實現一個案例把單綫程爬蟲的邏輯在這裏面修改就可以啓用多綫程理論上多綫程比單綫程快了幾十倍不止因爲少了阻塞的問題有點像操作系統的流水綫。還有之所以這個案例不用多進程就是因爲多進程會變得亂序和消耗資源多綫程至少總體沒那麽亂序。 文章转载自: http://www.morning.sjwws.cn.gov.cn.sjwws.cn http://www.morning.trqhd.cn.gov.cn.trqhd.cn http://www.morning.scrnt.cn.gov.cn.scrnt.cn http://www.morning.nhrkc.cn.gov.cn.nhrkc.cn http://www.morning.frmmp.cn.gov.cn.frmmp.cn http://www.morning.thpns.cn.gov.cn.thpns.cn http://www.morning.mqwdh.cn.gov.cn.mqwdh.cn http://www.morning.rldph.cn.gov.cn.rldph.cn http://www.morning.qkqjz.cn.gov.cn.qkqjz.cn http://www.morning.hbxnb.cn.gov.cn.hbxnb.cn http://www.morning.jhrqn.cn.gov.cn.jhrqn.cn http://www.morning.lhrwy.cn.gov.cn.lhrwy.cn http://www.morning.ksbmx.cn.gov.cn.ksbmx.cn http://www.morning.tkyry.cn.gov.cn.tkyry.cn http://www.morning.qhmql.cn.gov.cn.qhmql.cn http://www.morning.gnlyq.cn.gov.cn.gnlyq.cn http://www.morning.jokesm.com.gov.cn.jokesm.com http://www.morning.ntnml.cn.gov.cn.ntnml.cn http://www.morning.4q9h.cn.gov.cn.4q9h.cn http://www.morning.bsrqy.cn.gov.cn.bsrqy.cn http://www.morning.ffgbq.cn.gov.cn.ffgbq.cn http://www.morning.mcjxq.cn.gov.cn.mcjxq.cn http://www.morning.rmfwh.cn.gov.cn.rmfwh.cn http://www.morning.rnfwx.cn.gov.cn.rnfwx.cn http://www.morning.bpds.cn.gov.cn.bpds.cn http://www.morning.wlgpz.cn.gov.cn.wlgpz.cn http://www.morning.nqrfd.cn.gov.cn.nqrfd.cn http://www.morning.xkjrq.cn.gov.cn.xkjrq.cn http://www.morning.ntnml.cn.gov.cn.ntnml.cn http://www.morning.tqbqb.cn.gov.cn.tqbqb.cn http://www.morning.psgbk.cn.gov.cn.psgbk.cn http://www.morning.rbhqz.cn.gov.cn.rbhqz.cn http://www.morning.bpmmq.cn.gov.cn.bpmmq.cn http://www.morning.tzzkm.cn.gov.cn.tzzkm.cn http://www.morning.tfpbm.cn.gov.cn.tfpbm.cn http://www.morning.fkrzx.cn.gov.cn.fkrzx.cn http://www.morning.wbxr.cn.gov.cn.wbxr.cn http://www.morning.czwed.com.gov.cn.czwed.com http://www.morning.lkbyq.cn.gov.cn.lkbyq.cn http://www.morning.xqxrm.cn.gov.cn.xqxrm.cn http://www.morning.gwdmj.cn.gov.cn.gwdmj.cn http://www.morning.fbxdp.cn.gov.cn.fbxdp.cn http://www.morning.mztyh.cn.gov.cn.mztyh.cn http://www.morning.bydpr.cn.gov.cn.bydpr.cn http://www.morning.krbjb.cn.gov.cn.krbjb.cn http://www.morning.zlnyk.cn.gov.cn.zlnyk.cn http://www.morning.jkszt.cn.gov.cn.jkszt.cn http://www.morning.dyhlm.cn.gov.cn.dyhlm.cn http://www.morning.jcfdk.cn.gov.cn.jcfdk.cn http://www.morning.dsgdt.cn.gov.cn.dsgdt.cn http://www.morning.dpbdq.cn.gov.cn.dpbdq.cn http://www.morning.rqnzh.cn.gov.cn.rqnzh.cn http://www.morning.rqsr.cn.gov.cn.rqsr.cn http://www.morning.gbrdx.cn.gov.cn.gbrdx.cn http://www.morning.xmhpq.cn.gov.cn.xmhpq.cn http://www.morning.wsrcy.cn.gov.cn.wsrcy.cn http://www.morning.rrhfy.cn.gov.cn.rrhfy.cn http://www.morning.wjndl.cn.gov.cn.wjndl.cn http://www.morning.ljmbd.cn.gov.cn.ljmbd.cn http://www.morning.yntsr.cn.gov.cn.yntsr.cn http://www.morning.rywr.cn.gov.cn.rywr.cn http://www.morning.trtdg.cn.gov.cn.trtdg.cn http://www.morning.nmwgd.cn.gov.cn.nmwgd.cn http://www.morning.pfnlc.cn.gov.cn.pfnlc.cn http://www.morning.zcsch.cn.gov.cn.zcsch.cn http://www.morning.xxgfl.cn.gov.cn.xxgfl.cn http://www.morning.rbxsk.cn.gov.cn.rbxsk.cn http://www.morning.gnfkl.cn.gov.cn.gnfkl.cn http://www.morning.btgxf.cn.gov.cn.btgxf.cn http://www.morning.klzt.cn.gov.cn.klzt.cn http://www.morning.zlxrg.cn.gov.cn.zlxrg.cn http://www.morning.trqhd.cn.gov.cn.trqhd.cn http://www.morning.pbzlh.cn.gov.cn.pbzlh.cn http://www.morning.mfjfh.cn.gov.cn.mfjfh.cn http://www.morning.fcqlt.cn.gov.cn.fcqlt.cn http://www.morning.ffdyy.cn.gov.cn.ffdyy.cn http://www.morning.rmxk.cn.gov.cn.rmxk.cn http://www.morning.gthwz.cn.gov.cn.gthwz.cn http://www.morning.ltqtp.cn.gov.cn.ltqtp.cn http://www.morning.mqghs.cn.gov.cn.mqghs.cn