初学python和爬虫,正好赶上要在帝都租房,于是打算自己抓下链家的租房数据试试。看到网上有人抓取链家的二手房买卖数据,参考了下,不过我抓租房数据的时候发现还比较简单,不需要模拟登陆,链家也没怎么反爬虫,因而一路还比较顺利。
总体思路,虽然链家没有采用太多的反爬虫技术,但是基本的限制IP访问密度还是做了的,所以得动用代理,这么一来,抓取效率也必然降低,所以得采用多线程。实现的时候先实现代理的抓取,然后实现单线程单页面的抓取,接着改为多线程,再结合代理。
先看下代理部分。网上搜索了下,几个不断更新的免费的代理平台有,快代理、西刺代理和proxy360。那就针对这几个网站,分别封装类,提取代理IP和端口呗。限于初学,为了扎实基本功,就用了最笨的正则表达式提取数据。
先把代码全部贴出来:
# coding=utf-8
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'ATP'
import urllib
import urllib2
import re
import time
import threading
import socket
from bs4 import BeautifulSoup
import sys
import random
import getProxy
reload(sys)
sys.setdefaultencoding('utf-8')
BSparser = 'html.parser'
UserAgents=['Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6',
'Mozilla/5.0 (Windows NT 6.2) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.12 Safari/535.11',
'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)',
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:34.0) Gecko/20100101 Firefox/34.0',
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/44.0.2403.89 Chrome/44.0.2403.89 Safari/537.36',
'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50',
'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50',
'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1',
'Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11',
'Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11',
'Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11',
'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko',
'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.130 Safari/537.36']
#obtain proxy from proxy360.cn
class proxy_proxy360:
def __init__(self):
self.region=['Brazil','China','America','Taiwan','Japan','Thailand','Vietnam','bahrein']
self.root_url = 'http://www.proxy360.cn/Region/'
self.qqproxy_url='http://www.proxy360.cn/QQ-Proxy'
self.msnproxy_url = 'http://www.proxy360.cn/MSN-Proxy'
def getUrlList(self,proxyType='normal',proxyLocation='China'):
url = []
if proxyType == 'normal' or proxyType == 'all':
if proxyLocation == 'all':
for ri in self.region:
url.append(self.root_url + ri)
else:
url.append(self.root_url + proxyLocation)
if proxyType == 'qq' or proxyType == 'all':
url.append(self.qqproxy_url)
if proxyType == 'msn' or proxyType == 'all':
url.append(self.msnproxy_url)
return url
def getProxy(self,url=[]):
items = []
try:
for urlitem in url:
print 'Get proxy from url: ' + urlitem
#request = urllib2.Request(urlitem,headers=headers)
request = urllib2.Request(urlitem)
response = urllib2.urlopen(request)
content = response.read().decode('utf-8')
pattern = re.compile(r'.*?>'
r'.*?>\s*(.*?)\s*'
r'.*?>\s*(.*?)\s*'
r'.*?>\s*(.*?)\s*'
r'.*?>\s*(.*?)\s*'
r'.*?>\s*(.*?)\s*'
r'.*?>\s*(.*?)\s*'
r'.*?>\s*(.*?)\s*'
r'.*?>\s*(.*?)\s*'
r'.*?/div>.*?>.*?', re.S)
itemslist = re.findall(pattern,content)
for itemsnew in itemslist:
itemproperty = {}
itemproperty['ip']=itemsnew[0]
itemproperty['port'] = itemsnew[1]
itemproperty['anony_degree'] = itemsnew[2]
itemproperty['location'] = itemsnew[3]
itemproperty['updata_time'] = itemsnew[4]
itemproperty['today_mark'] = itemsnew[5]
itemproperty['total_mark'] = itemsnew[6]
itemproperty['available_time'] = itemsnew[7]
itemproperty['speed'] = itemsnew[8]
items.append(itemproperty)
except (urllib2.HTTPError, urllib2.URLError), e:
print e
except Exception,e:
print e
return items
#obtain proxy from kuaidaili.com
class proxy_kuaidaili:
def __init__(self):
self.root_latest = 'http://www.kuaidaili.com/proxylist/'
self.root_free = 'http://www.kuaidaili.com/free/'
self.freeType = ['latest','inha','intr','outha','outtr']
def getUrlList(self,proxyType='latest',pageNum=10):
url = []
if proxyType == 'latest':
for i in range(0,min(pageNum,10)):
url.append(self.root_latest+str(i+1))
elif proxyType in self.freeType:
try:
urlitem = self.root_free + proxyType
request = urllib2.Request(urlitem)
response = urllib2.urlopen(request)
content = response.read().decode('utf-8')
pattern = re.compile(u'(.*?)
\u9875 ',re.S)
lastPage = re.findall(pattern,content)
if lastPage:
for i in range(0,min(pageNum,int(lastPage[0]))):
url.append(urlitem+'/'+str(i+1))
except (urllib2.HTTPError, urllib2.URLError), e:
print e
except Exception,e:
print e
else:
print "Input error no such type of proxy:"+proxyType
return url
def getProxy(self,url=[]):
proxy = []
for urlitem in url:
try:
print "Get proxy from url: " + urlitem
request = urllib2.Request(urlitem)
response = urllib2.urlopen(request)
content = response.read().decode('utf-8')
pattern = re.compile(r'
IP<.*?PORT.*?\s*(.*?) ',re.S)
proxyTable = re.findall(pattern,content)
if proxyTable:
content=proxyTable[0]
pattern = re.compile(r'get/post')
bGET_POST = re.findall(pattern,content)
if bGET_POST:
pattern = re.compile(r'.*?(.*?)'
r'.*?(.*?)'
r'.*?(.*?)'
r'.*?(.*?)'
r'.*?(.*?)'
r'.*?(.*?)'
r'.*?(.*?)'
r'.*?(.*?)',re.S)
proxylistget = re.findall(pattern,content)
for proxyitem in proxylistget:
proxyitem_property = {}
proxyitem_property['ip'] = proxyitem[0]
proxyitem_property['port'] = proxyitem[1]
proxyitem_property['anony_degree'] = proxyitem[2]
proxyitem_property['proxy_type'] = proxyitem[3]
proxyitem_property['get_post_support'] = proxyitem[4]
proxyitem_property['location'] = proxyitem[5]
proxyitem_property['speed'] = proxyitem[6]
proxyitem_property['last_verify_time'] = proxyitem[7]
proxy.append(proxyitem_property)
else :
pattern = re.compile(r'.*?(.*?)'
r'.*?(.*?)'
r'.*?(.*?)'
r'.*?(.*?)'
r'.*?(.*?)'
r'.*?(.*?)'
r'.*?(.*?)', re.S)
proxylistget = re.findall(pattern, content)
for proxyitem in proxylistget:
proxyitem_property = {}
proxyitem_property['ip'] = proxyitem[0]
proxyitem_property['port'] = proxyitem[1]
proxyitem_property['anony_degree'] = proxyitem[2]
proxyitem_property['proxy_type'] = proxyitem[3]
proxyitem_property['location'] = proxyitem[4]
proxyitem_property['speed'] = proxyitem[5]
proxyitem_property['last_verify_time'] = proxyitem[6]
proxy.append(proxyitem_property)
except (urllib2.HTTPError, urllib2.URLError), e:
print e
except Exception,e:
print e
return proxy
class proxy_xicidaili:
def __init__(self):
self.root_url = 'http://www.xicidaili.com/'
self.proxy_type = ['nn','nt','wn','wt','qq']
self.user_agent = UserAgents[14]
def getUrlList(self,proxyType='nn',pageNum=10):
url = []
if proxyType == 'all':
for item in self.proxy_type:
url.extend(self.getUrlList(item,pageNum))
elif proxyType in self.proxy_type:
try:
urlitem = self.root_url + proxyType
headers = {'User-Agent': self.user_agent}
request = urllib2.Request(urlitem,headers=headers)
response = urllib2.urlopen(request)
content = response.read().decode('utf-8')
soup = BeautifulSoup(content,BSparser)
atag = soup.find(class_='next_page')
num = int(atag.find_previous_sibling().string)
for i in range(0,min(num,pageNum)):
url.append(urlitem+'/'+str(i+1))
except (urllib2.HTTPError, urllib2.URLError), e:
print e
except Exception,e:
print e
else:
print "Input error no such type of proxy:" + proxyType
return url
def getProxy(self,url=[]):
proxy = []
for urlitem in url:
try:
print "get proxy from url: " + urlitem
headers = {'User-Agent': self.user_agent}
request = urllib2.Request(urlitem, headers=headers)
response = urllib2.urlopen(request)
content = response.read().decode('utf-8')
soup = BeautifulSoup(content, BSparser)
tabletag = soup.find(id='ip_list')
thtag = tabletag.find('tr')
trtags = thtag.find_next_siblings('tr')
for trtag in trtags:
tdtags = trtag.find_all('td',recursive=False)
proxyitem_property = {}
if tdtags[0].img:
proxyitem_property['country']=tdtags[0].img['alt']
else:
proxyitem_property['country']=tdtags[0].string
proxyitem_property['ip'] = tdtags[1].string
proxyitem_property['port'] = tdtags[2].string
if tdtags[3].a :
proxyitem_property['location'] = tdtags[3].a.string
locatext = tdtags[3].a['href']
pattern = re.compile(r'/[\-0-9]/(.*?)')
loca = re.findall(pattern, locatext)
if loca:
proxyitem_property['location-pinyin'] = loca[0]
else:
proxyitem_property['location'] = tdtags[3].string
proxyitem_property['anony_degree'] = tdtags[4].string
proxyitem_property['proxy_type'] = tdtags[5].string
proxyitem_property['speed'] = tdtags[6].div['title']
proxyitem_property['connect_speed'] = tdtags[7].div['title']
proxyitem_property['alive_time'] = tdtags[8].string
proxyitem_property['last_verify_time'] = tdtags[9].string
proxy.append(proxyitem_property)
except (urllib2.HTTPError, urllib2.URLError), e:
print e
except Exception,e:
print e
return proxy
def proxyValidate(target_url, key_word, proxylist,timeout=5):
resultList = {}
for proxy in proxylist:
try:
starttime = time.time()
headers = {'User-Agent': UserAgents[random.randint(0, len(UserAgents) - 1)]}
proxy_handler = urllib2.ProxyHandler({"http": proxy})
opener = urllib2.build_opener(proxy_handler)
urllib2.install_opener(opener)
request = urllib2.Request(target_url, headers=headers)
response = urllib2.urlopen(request,timeout=timeout)
content = response.read().decode('utf-8')
pattern = re.compile(unicode(key_word), re.S)
keywordFind = re.findall(pattern, content)
endtime = time.time()
if keywordFind:
proxyAvailable = 'true'
print ' proxy: %s --%s thread: %s time %s'% (proxy,'success',threading.current_thread().name,endtime - starttime)
plistlock.acquire()
try:
successList[proxy]=endtime-starttime
finally:
plistlock.release()
else:
proxyAvailable = 'false'
print ' proxy: %s --%s thread: %s time %s' % (proxy,'failed',threading.current_thread().name,endtime - starttime)
plistlock.acquire()
try:
failList[proxy]=endtime-starttime
finally:
plistlock.release()
except (urllib2.HTTPError, urllib2.URLError), e:
proxyAvailable = str(e)
print ' proxy: %s -httperror-%s thread: %s'% (proxy,e,threading.current_thread().name)
except Exception, e:
proxyAvailable = str(e)
print ' proxy: %s -other-%s thread: %s'% (proxy,e,threading.current_thread().name)
if proxyAvailable != 'true' and 'false' != proxyAvailable:
plistlock.acquire()
try:
errorList[proxy]=proxyAvailable
finally:
plistlock.release()
resultList[str(proxy)] = proxyAvailable
return resultList
#what if python2.7 support variable parameters, things will go easier...make it more universally
def multiThreadValidate(dealList,threadnum,func,args,joinImmediate = True):
if len(dealList) == 0:
return
successList.clear()
failList.clear()
errorList.clear()
listLen = len(dealList)
threadlist = []
apartNum = (len(dealList)-1)/threadnum+1
if apartNum < 2:
apartNum = 2
ctn = apartNum -1
while ctn < listLen:
th = threading.Thread(target=func, args=(args[0],args[1],dealList[ctn-apartNum+1:ctn+1]),name=str(ctn / apartNum))
th.start()
threadlist.append(th)
ctn = ctn + apartNum
if listLen % apartNum != 0:
th = threading.Thread(target=func, args=(args[0],args[1],dealList[ctn-apartNum+1:listLen]),name=str(ctn / apartNum))
th.start()
threadlist.append(th)
if joinImmediate:
for ti in threadlist:
ti.join()
return threadlist
successList = {} #format: {'proxyip:port':'time of access',}
failList = {}
errorList = {}
plistlock = threading.RLock()
if __name__=="__main__":
starttime = time.time()
spider = proxy_kuaidaili()
url = spider.getUrlList('outha',10)
proxy_items = spider.getProxy(url)
print 'num of proxy to be test: '+ str(len(proxy_items))
proxylist = []
for proxyi in proxy_items:
proxylist.append(proxyi['ip'] + ':' + proxyi['port'])
socket.setdefaulttimeout(5)
multiThreadValidate(proxylist,20,proxyValidate,('http://bj.lianjia.com/','了解链家网'.decode())) #
print len(successList)
for i in successList:
print '%s : %s ' % (i,successList[i])
endtime = time.time()
print 'total time cost: %s' % str(endtime-starttime)
几个类都类似,如果放C#下面,可以实现个接口。getUrlList先生成可以抓取的页面URL,然后getproxy抓取代理服务器IP端口。此外定义了proxyValidate和multiThreadValidate对抓取的代理服务器进行验证,毕竟免费的质量毕竟低,很多是用不了或者可用时间很短。验证的时候就下载指定url,并匹配关键词,匹配成功则表明服务器可用,这是最简单的做法。multiThreadValidate用了多线程的方法,每个线程还是执行proxyValidate进行验证,但是在该函数进行了任务拆分。
真正进行到链家数据抓取,考虑到数据量比较大(不适合写入文本,但又不至于动用高性能大型数据库),但有都是结构化数据,为了高效存储,采用轻量级的sqlite,考虑到多线程操作数据库,必然带来访问一致性问题,而网络IO较慢,数据库读写频率不高,可以加个线程锁保证单次只有一个线程访问。
数据库封装如下:
class SQLiteWraper(object):
def __init__(self,conn_arg,command='',*args,**kwargs):
self.lock = threading.RLock()
self.path = conn_arg
if command!='':
conn=self.get_conn()
cu=conn.cursor()
cu.execute(command)
def get_conn(self):
conn = sqlite3.connect(self.path)#,check_same_thread=False)
conn.text_factory=str
return conn
def conn_close(self,conn=None):
conn.close()
def conn_trans(func):
def connection(self,*args,**kwargs):
self.lock.acquire()
conn = self.get_conn()
kwargs['conn'] = conn
rs = func(self,*args,**kwargs)
self.conn_close(conn)
self.lock.release()
return rs
return connection
@conn_trans
def execute(self, command, conn=None):
cu = conn.cursor()
try:
cu.execute(command)
conn.commit()
except sqlite3.IntegrityError, e:
print e
return -1
except Exception, e:
print e
return -2
return 0
@conn_trans
def fetchall(self,command="select count(*)",conn=None):
cu=conn.cursor()
lists=[]
try:
cu.execute(command)
lists=cu.fetchall()
except Exception,e:
print e
return lists
其中为了保证线程锁不被滥用造成死锁,以及数据库连接能被及时关闭,定义了一个高阶函数conn_trans,也即装饰器函数(decorator)。定义了一个全局函数createDB来初始化数据库。仅执行一次。
抓取链家数据的类结构如下:
class crawlLianJia:
def __init__(self):
pass
def threadUpdateProxy(self):
pass
def getContentbyProxy(self,url,succPattern='',failPattern='',succCheckFirst= False,tryMax = 10,timeout = 10):
pass
#craw with single thread, about 1,000 accesses to the lianjia website will be ip blocked
def crawAllRentInfo(self):
pass
#craw with multiple threads
def crawAllRentInfo_multi(self,threadnum):
pass
#python 2.7 does not support variable parameters very well, pity
def multiThreadCrawList(self,threadnum,deallist,func,threadNamePrefix='',joinImmediate = True,*argspass,**kwargs):
pass
#get regions from website than craw by regions because the website only presents 100 pages in response
def getRegion(self):
pass
#save regions and bizcircles(subRegions) crawed to database, because the regions only need to craw once
def updateRegionInfo(self):
pass
def getRegionFromDB(self):
pass
#craw info of the given regions
def crawRentInfo_Regions(self,subRegionList):
pass
#return a list of pages to be crawed in the region
def crawRentInfo_certainRegion(self,region):
pass
#save all pages need be crawed to database
def updatePageList(self):
pass
def getPageListFromDB(self):
pass
def crawRentInfo_Pages(self,pageList=[]):
pass
def crawRentInfo_certainPage(self,urlpage):
pass
def crawRentInfo_pageTagInfo(self,tagText):
pass
def crawRentInfo_certainRoom(self,hid,isRemoved=False):
pass
def crawRentInfo_community(self,cid):
pass
def crawRentInfo_json(self,HID,CID):
pass
#return true of false to indicate whether a room is in database(has been crawed)
def dealRentRoomCrawed(self,hid):
pass
def dealRentCommunityCrawed(self,cid):
pass
#insert a new record into a certain table of database
def insertInfo(self,table='',infoDic={}):
pass
#update the infomation of certain record
def updateInfo(self,table,primaryKey,infoDic={}):
pass
#insert some key-value pairs to the table
def insertDicListInfo(self,table='',infoDicList=[]):
pass
def loadErrorListFromFile(self,filename = 'errorlist'):
pass
def dumpErrorListToFile(self,filename = 'errorlist'):
pass
def recrawError_Comms(self,commList):
pass
def recrawError_Rooms(self,roomList):
pass
def recrawErrorList_multi(self,threadnum=10):
pass
def recrawErrorList(self):
pass
def createDB():
pass
if __name__=="__main__":
这里涉及几个多线程访问的列表变量,allPages表示待抓取的所有页面url,errorPageUrlList是抓取错误的页面url,errorRoomList是抓取房屋信息时发生错误的房屋ID,errorCommList是抓取小区信息失败时的小区ID。proxyList是可用代理服务器列表,一直更新中。proxyForceoutList是被网站封杀了的代理服务器列表。
首先是几个用于验证代理服务器是否可用的函数,threadUpdateProxy为主函数,程序启动后也随之启动,里面主要为一个死循环,判断当可用代理服务器列表proxyListOld小于阈值,启动抓取代理服务器,执行multiThreadValidate函数,参见前述getProxy模块。
getContentbyProxy完成使用代理服务器下载指定页面内容的功能。仅负责下载内容,解析由其他函数完成,参见后文。
这里得说两句,链家的租房信息是树状分布,以北京为例,顶层是按几大城区(东城、西城、海淀、大兴、顺义等等,程序中用mainRegion表示)分,然后是各区内的小街区(如东城区内的安定门、安贞、朝阳门外、前门等等,程序中用region或者subRegion表示),再然后是出租房数据。链家限制一次最多呈现100个页面的结果,每个页面三十条数据,因此不能直接按几大城区+页码的形式构造url获取查询结果。而通常子街区包含的结果数不超过30页,子街区之间又不重复,故而可以直接按子街区,然后按页构造url以此获取全部数据。这里我先将所有的子街区下载好,按页将url构造好并保存到数据库免去每次测试期间每次启动爬虫重新构造url的麻烦。
crawAllRentInfo为单线程版,仅测试用。实际采用crawAllRentInfo_multi函数,该函数调用multiThreadCrawList抓取所有带抓取页面url。multiThreadCrawList用多线程执行crawRentInfo_Regions,传入参数subRegionList包含子区域列表,由crawRentInfo_Regions调用crawRentInfo_certainRegion抓取每个子区域的搜索结果页url并返回。最终crawAllRentInfo_mult得到所有带抓取的页面url,然后再调用multiThreadCrawList开启多线程抓取所有页面,传入的抓取函数为crawRentInfo_Pages。第一次抓取到所有页面url可以用updatePageList()将页面url更新到数据库,后续执行可以直接用注释的语句getPageListFromDB()完成所有页面url获取。当然不想用多线程抓取所有页面url可以直接用crawRentInfo_Regions(self.regionUnrepeat)。
crawRentInfo_certainPage根据url抓取指定搜索结果页面,用正则表达式匹配出该页面上的房屋结果信息,crawRentInfo_pageTagInfo抓取搜索结果页上的特有的房屋标签信息(详情页里没有的)。然后根据房屋的ID信息转由crawRentInfo_certainRoom进一步抓取该ID房屋详细信息,由crawRentInfo_community进一步抓取对应的小区信息。由crawRentInfo_json抓取由json传送的带看信息。
后续的insertInfo根据表名和字段字典构造数据库插入sql语句并插入。updateInfo构造数据库更新语句并执行。insertDicListInfo批量插入数据。dumpErrorListToFile将抓取错误的数据以json形式序列化到文档中。loadErrorListFromFile完成对应的反序列化工作。recrawErrorList_multi多线程方式重新抓取之前抓取失败的各种信息。调用recrawError_Comms重新抓取之前抓取失败的小区信息。调用recrawError_Rooms同理。
剩下的没啥好说的啦。入口函数依次执行。
更多信息见原文: http://www.straka.cn/blog/python_craw_lianjia /
你可能感兴趣的:(software,diy,python)
理解Gunicorn:Python WSGI服务器的基石
范范0825
ipython linux 运维
理解Gunicorn:PythonWSGI服务器的基石介绍Gunicorn,全称GreenUnicorn,是一个为PythonWSGI(WebServerGatewayInterface)应用设计的高效、轻量级HTTP服务器。作为PythonWeb应用部署的常用工具,Gunicorn以其高性能和易用性著称。本文将介绍Gunicorn的基本概念、安装和配置,帮助初学者快速上手。1.什么是Gunico
Python数据分析与可视化实战指南
William数据分析
python python 数据
在数据驱动的时代,Python因其简洁的语法、强大的库生态系统以及活跃的社区,成为了数据分析与可视化的首选语言。本文将通过一个详细的案例,带领大家学习如何使用Python进行数据分析,并通过可视化来直观呈现分析结果。一、环境准备1.1安装必要库在开始数据分析和可视化之前,我们需要安装一些常用的库。主要包括pandas、numpy、matplotlib和seaborn等。这些库分别用于数据处理、数学
python os.environ
江湖偌大
python 深度学习
os.environ['TF_CPP_MIN_LOG_LEVEL']='0'#默认值,输出所有信息os.environ['TF_CPP_MIN_LOG_LEVEL']='1'#屏蔽通知信息(INFO)os.environ['TF_CPP_MIN_LOG_LEVEL']='2'#屏蔽通知信息和警告信息(INFO\WARNING)os.environ['TF_CPP_MIN_LOG_LEVEL']='
Python中os.environ基本介绍及使用方法
鹤冲天Pro
# Python python 服务器 开发语言
文章目录python中os.environos.environ简介os.environ进行环境变量的增删改查python中os.environ的使用详解1.简介2.key字段详解2.1常见key字段3.os.environ.get()用法4.环境变量的增删改查和判断是否存在4.1新增环境变量4.2更新环境变量4.3获取环境变量4.4删除环境变量4.5判断环境变量是否存在python中os.envi
Pyecharts数据可视化大屏:打造沉浸式数据分析体验
我的运维人生
信息可视化 数据分析 数据挖掘 运维开发 技术共享
Pyecharts数据可视化大屏:打造沉浸式数据分析体验在当今这个数据驱动的时代,如何将海量数据以直观、生动的方式展现出来,成为了数据分析师和企业决策者关注的焦点。Pyecharts,作为一款基于Python的开源数据可视化库,凭借其丰富的图表类型、灵活的配置选项以及高度的定制化能力,成为了构建数据可视化大屏的理想选择。本文将深入探讨如何利用Pyecharts打造数据可视化大屏,并通过实际代码案例
Python教程:一文了解使用Python处理XPath
旦莫
Python进阶 python 开发语言
目录1.环境准备1.1安装lxml1.2验证安装2.XPath基础2.1什么是XPath?2.2XPath语法2.3示例XML文档3.使用lxml解析XML3.1解析XML文档3.2查看解析结果4.XPath查询4.1基本路径查询4.2使用属性查询4.3查询多个节点5.XPath的高级用法5.1使用逻辑运算符5.2使用函数6.实战案例6.1从网页抓取数据6.1.1安装Requests库6.1.2代
python os.environ_python os.environ 读取和设置环境变量
weixin_39605414
python os.environ
>>>importos>>>os.environ.keys()['LC_NUMERIC','GOPATH','GOROOT','GOBIN','LESSOPEN','SSH_CLIENT','LOGNAME','USER','HOME','LC_PAPER','PATH','DISPLAY','LANG','TERM','SHELL','J2REDIR','LC_MONETARY','QT_QPA
使用Faiss进行高效相似度搜索
llzwxh888
faiss python
在现代AI应用中,快速和高效的相似度搜索是至关重要的。Faiss(FacebookAISimilaritySearch)是一个专门用于快速相似度搜索和聚类的库,特别适用于高维向量。本文将介绍如何使用Faiss来进行相似度搜索,并结合Python代码演示其基本用法。什么是Faiss?Faiss是一个由FacebookAIResearch团队开发的开源库,主要用于高维向量的相似性搜索和聚类。Faiss
python是什么意思中文-在python中%是什么意思
编程大乐趣
Python中%有两种:1、数值运算:%代表取模,返回除法的余数。如:>>>7%212、%操作符(字符串格式化,stringformatting),说明如下:%[(name)][flags][width].[precision]typecode(name)为命名flags可以有+,-,''或0。+表示右对齐。-表示左对齐。''为一个空格,表示在正数的左侧填充一个空格,从而与负数对齐。0表示使用0填
Day1笔记-Python简介&标识符和关键字&输入输出
~在杰难逃~
Python python 开发语言 大数据 数据分析 数据挖掘
大家好,从今天开始呢,杰哥开展一个新的专栏,当然,数据分析部分也会不定时更新的,这个新的专栏主要是讲解一些Python的基础语法和知识,帮助0基础的小伙伴入门和学习Python,感兴趣的小伙伴可以开始认真学习啦!一、Python简介【了解】1.计算机工作原理编程语言就是用来定义计算机程序的形式语言。我们通过编程语言来编写程序代码,再通过语言处理程序执行向计算机发送指令,让计算机完成对应的工作,编程
python八股文面试题分享及解析(1)
Shawn________
python
#1.'''a=1b=2不用中间变量交换a和b'''#1.a=1b=2a,b=b,aprint(a)print(b)结果:21#2.ll=[]foriinrange(3):ll.append({'num':i})print(11)结果:#[{'num':0},{'num':1},{'num':2}]#3.kk=[]a={'num':0}foriinrange(3):#0,12#可变类型,不仅仅改变
每日算法&面试题,大厂特训二十八天——第二十天(树)
肥学
⚡算法题⚡面试题每日精进 java 算法 数据结构
目录标题导读算法特训二十八天面试题点击直接资料领取导读肥友们为了更好的去帮助新同学适应算法和面试题,最近我们开始进行专项突击一步一步来。上一期我们完成了动态规划二十一天现在我们进行下一项对各类算法进行二十八天的一个小总结。还在等什么快来一起肥学进行二十八天挑战吧!!特别介绍小白练手专栏,适合刚入手的新人欢迎订阅编程小白进阶python有趣练手项目里面包括了像《机器人尬聊》《恶搞程序》这样的有趣文章
Python快速入门 —— 第三节:类与对象
孤华暗香
Python快速入门 python 开发语言
第三节:类与对象目标:了解面向对象编程的基础概念,并学会如何定义类和创建对象。内容:类与对象:定义类:class关键字。类的构造函数:__init__()。类的属性和方法。对象的创建与使用。示例:classStudent:def__init__(self,name,age,major):self.name
pyecharts——绘制柱形图折线图
2224070247
信息可视化 python java 数据可视化
一、pyecharts概述自2013年6月百度EFE(ExcellentFrontEnd)数据可视化团队研发的ECharts1.0发布到GitHub网站以来,ECharts一直备受业界权威的关注并获得广泛好评,成为目前成熟且流行的数据可视化图表工具,被应用到诸多数据可视化的开发领域。Python作为数据分析领域最受欢迎的语言,也加入ECharts的使用行列,并研发出方便Python开发者使用的数据
Python 实现图片裁剪(附代码) | Python工具
剑客阿良_ALiang
前言本文提供将图片按照自定义尺寸进行裁剪的工具方法,一如既往的实用主义。环境依赖ffmpeg环境安装,可以参考我的另一篇文章:windowsffmpeg安装部署_阿良的博客-CSDN博客本文主要使用到的不是ffmpeg,而是ffprobe也在上面这篇文章中的zip包中。ffmpy安装:pipinstallffmpy-ihttps://pypi.douban.com/simple代码不废话了,上代码
【华为OD技术面试真题 - 技术面】- python八股文真题题库(4)
算法大师
华为od 面试 python
华为OD面试真题精选专栏:华为OD面试真题精选目录:2024华为OD面试手撕代码真题目录以及八股文真题目录文章目录华为OD面试真题精选**1.Python中的`with`**用途和功能自动资源管理示例:文件操作上下文管理协议示例代码工作流程解析优点2.\_\_new\_\_和**\_\_init\_\_**区别__new____init__区别总结3.**切片(Slicing)操作**基本切片语法
python os 环境变量
CV矿工
python 开发语言 numpy
环境变量:环境变量是程序和操作系统之间的通信方式。有些字符不宜明文写进代码里,比如数据库密码,个人账户密码,如果写进自己本机的环境变量里,程序用的时候通过os.environ.get()取出来就行了。os.environ是一个环境变量的字典。环境变量的相关操作importos"""设置/修改环境变量:os.environ[‘环境变量名称’]=‘环境变量值’#其中key和value均为string类
Python爬虫解析工具之xpath使用详解
eqa11
python 爬虫 开发语言
文章目录Python爬虫解析工具之xpath使用详解一、引言二、环境准备1、插件安装2、依赖库安装三、xpath语法详解1、路径表达式2、通配符3、谓语4、常用函数四、xpath在Python代码中的使用1、文档树的创建2、使用xpath表达式3、获取元素内容和属性五、总结Python爬虫解析工具之xpath使用详解一、引言在Python爬虫开发中,数据提取是一个至关重要的环节。xpath作为一门
【华为OD技术面试真题 - 技术面】- python八股文真题题库(1)
算法大师
华为od 面试 python
华为OD面试真题精选专栏:华为OD面试真题精选目录:2024华为OD面试手撕代码真题目录以及八股文真题目录文章目录华为OD面试真题精选1.数据预处理流程数据预处理的主要步骤工具和库2.介绍线性回归、逻辑回归模型线性回归(LinearRegression)模型形式:关键点:逻辑回归(LogisticRegression)模型形式:关键点:参数估计与评估:3.python浅拷贝及深拷贝浅拷贝(Shal
nosql数据库技术与应用知识点
皆过客,揽星河
NoSQL nosql 数据库 大数据 数据分析 数据结构 非关系型数据库
Nosql知识回顾大数据处理流程数据采集(flume、爬虫、传感器)数据存储(本门课程NoSQL所处的阶段)Hdfs、MongoDB、HBase等数据清洗(入仓)Hive等数据处理、分析(Spark、Flink等)数据可视化数据挖掘、机器学习应用(Python、SparkMLlib等)大数据时代存储的挑战(三高)高并发(同一时间很多人访问)高扩展(要求随时根据需求扩展存储)高效率(要求读写速度快)
《Python数据分析实战终极指南》
xjt921122
python 数据分析 开发语言
对于分析师来说,大家在学习Python数据分析的路上,多多少少都遇到过很多大坑**,有关于技能和思维的**:Excel已经没办法处理现有的数据量了,应该学Python吗?找了一大堆Python和Pandas的资料来学习,为什么自己动手就懵了?跟着比赛类公开数据分析案例练了很久,为什么当自己面对数据需求还是只会数据处理而没有分析思路?学了对比、细分、聚类分析,也会用PEST、波特五力这类分析法,为啥
Python中深拷贝与浅拷贝的区别
yuxiaoyu.
转自:http://blog.csdn.net/u014745194/article/details/70271868定义:在Python中对象的赋值其实就是对象的引用。当创建一个对象,把它赋值给另一个变量的时候,python并没有拷贝这个对象,只是拷贝了这个对象的引用而已。浅拷贝:拷贝了最外围的对象本身,内部的元素都只是拷贝了一个引用而已。也就是,把对象复制一遍,但是该对象中引用的其他对象我不复
Python开发常用的三方模块如下:
换个网名有点难
python 开发语言
Python是一门功能强大的编程语言,拥有丰富的第三方库,这些库为开发者提供了极大的便利。以下是100个常用的Python库,涵盖了多个领域:1、NumPy,用于科学计算的基础库。2、Pandas,提供数据结构和数据分析工具。3、Matplotlib,一个绘图库。4、Scikit-learn,机器学习库。5、SciPy,用于数学、科学和工程的库。6、TensorFlow,由Google开发的开源机
Python编译器
鹿鹿~
Python编译器 Python python 开发语言 后端
嘿嘿嘿我又来了啊有些小盆友可能不知道Python其实是有编译器的,也就是PyCharm。你们可能会问到这个是干嘛的又不可以吃也不可以穿好像没有什么用,其实你还说对了这个还真的不可以吃也不可以穿,但是它用来干嘛的呢。用来编译你所打出的代码进行运行(可能这里说的有点不对但是只是个人认为)现在我们来说说PyCharm是用来干嘛的。PyCharm是一种PythonIDE,带有一整套可以帮助用户在使用Pyt
一文掌握python面向对象魔术方法(二)
程序员neil
python python 开发语言
接上篇:一文掌握python面向对象魔术方法(一)-CSDN博客目录六、迭代和序列化:1、__iter__(self):定义迭代器,使得类可以被for循环迭代。2、__getitem__(self,key):定义索引操作,如obj[key]。3、__setitem__(self,key,value):定义赋值操作,如obj[key]=value。4、__delitem__(self,key):定义
一文掌握python常用的list(列表)操作
程序员neil
python python 开发语言
目录一、创建列表1.直接创建列表:2.使用list()构造器3.使用列表推导式4.创建空列表二、访问列表元素1.列表支持通过索引访问元素,索引从0开始:2.还可以使用切片操作访问列表的一部分:三、修改列表元素四、添加元素1.append():在末尾添加元素2.insert():在指定位置插入元素五、删除元素1.del:删除指定位置的元素2.remove():删除指定值的第一个匹配项3.pop():
Python实现简单的机器学习算法
master_chenchengg
python python 办公效率 python开发 IT
Python实现简单的机器学习算法开篇:初探机器学习的奇妙之旅搭建环境:一切从安装开始必备工具箱第一步:安装Anaconda和JupyterNotebook小贴士:如何配置Python环境变量算法初体验:从零开始的Python机器学习线性回归:让数据说话数据准备:从哪里找数据编码实战:Python实现线性回归模型评估:如何判断模型好坏逻辑回归:从分类开始理论入门:什么是逻辑回归代码实现:使用skl
python中的深拷贝与浅拷贝
anshejd70787
python
深拷贝和浅拷贝浅拷贝的时候,修改原来的对象,浅拷贝的对象不会发生改变。1、对象的赋值对象的赋值实际上是对象之间的引用:当创建一个对象,然后将这个对象赋值给另外一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用。当对对象做赋值或者是参数传递或者作为返回值的时候,总是传递原始对象的引用,而不是一个副本。如下所示:>>>aList=["kel","abc",123]>>>bLis
用Python实现简单的猜数字游戏
程序媛了了
python 游戏 java
猜数字游戏代码:importrandomdefpythonit():a=random.randint(1,100)n=int(input("输入你猜想的数字:"))whilen!=a:ifn>a:print("很遗憾,猜大了")n=int(input("请再次输入你猜想的数字:"))elifna::如果玩家猜的数字n大于随机数字a,则输出"很遗憾,猜大了",并提示玩家再次输入。elifn
用Python实现读取统计单词个数
程序媛了了
python 游戏 java
完整实例代码:fromcollectionsimportCounterdefpythonit():danci={}withopen("pythonit.txt","r",encoding="utf-8")asf:foriinf:words=i.strip().split()forwordinwords:ifwordnotindanci:danci[word]=1else:danci[word]+=
jvm调优总结(从基本概念 到 深度优化)
oloz
java jvm jdk 虚拟机 应用服务器
JVM参数详解:http://www.cnblogs.com/redcreen/archive/2011/05/04/2037057.html
Java虚拟机中,数据类型可以分为两类:基本类型和引用类型。基本类型的变量保存原始值,即:他代表的值就是数值本身;而引用类型的变量保存引用值。“引用值”代表了某个对象的引用,而不是对象本身,对象本身存放在这个引用值所表示的地址的位置。
【Scala十六】Scala核心十:柯里化函数
bit1129
scala
本篇文章重点说明什么是函数柯里化,这个语法现象的背后动机是什么,有什么样的应用场景,以及与部分应用函数(Partial Applied Function)之间的联系 1. 什么是柯里化函数
A way to write functions with multiple parameter lists. For instance
def f(x: Int)(y: Int) is a
HashMap
dalan_123
java
HashMap在java中对很多人来说都是熟的;基于hash表的map接口的非同步实现。允许使用null和null键;同时不能保证元素的顺序;也就是从来都不保证其中的元素的顺序恒久不变。
1、数据结构
在java中,最基本的数据结构无外乎:数组 和 引用(指针),所有的数据结构都可以用这两个来构造,HashMap也不例外,归根到底HashMap就是一个链表散列的数据
Java Swing如何实时刷新JTextArea,以显示刚才加append的内容
周凡杨
java 更新 swing JTextArea
在代码中执行完textArea.append("message")后,如果你想让这个更新立刻显示在界面上而不是等swing的主线程返回后刷新,我们一般会在该语句后调用textArea.invalidate()和textArea.repaint()。
问题是这个方法并不能有任何效果,textArea的内容没有任何变化,这或许是swing的一个bug,有一个笨拙的办法可以实现
servlet或struts的Action处理ajax请求
g21121
servlet
其实处理ajax的请求非常简单,直接看代码就行了:
//如果用的是struts
//HttpServletResponse response = ServletActionContext.getResponse();
// 设置输出为文字流
response.setContentType("text/plain");
// 设置字符集
res
FineReport的公式编辑框的语法简介
老A不折腾
finereport 公式 总结
FINEREPORT用到公式的地方非常多,单元格(以=开头的便被解析为公式),条件显示,数据字典,报表填报属性值定义,图表标题,轴定义,页眉页脚,甚至单元格的其他属性中的鼠标悬浮提示内容都可以写公式。
简单的说下自己感觉的公式要注意的几个地方:
1.if语句语法刚接触感觉比较奇怪,if(条件式子,值1,值2),if可以嵌套,if(条件式子1,值1,if(条件式子2,值2,值3)
linux mysql 数据库乱码的解决办法
墙头上一根草
linux mysql 数据库乱码
linux 上mysql数据库区分大小写的配置
lower_case_table_names=1 1-不区分大小写 0-区分大小写
修改/etc/my.cnf 具体的修改内容如下:
[client]
default-character-set=utf8
[mysqld]
datadir=/var/lib/mysql
socket=/va
我的spring学习笔记6-ApplicationContext实例化的参数兼容思想
aijuans
Spring 3
ApplicationContext能读取多个Bean定义文件,方法是:
ApplicationContext appContext = new ClassPathXmlApplicationContext(
new String[]{“bean-config1.xml”,“bean-config2.xml”,“bean-config3.xml”,“bean-config4.xml
mysql 基准测试之sysbench
annan211
基准测试 mysql基准测试 MySQL测试 sysbench
1 执行如下命令,安装sysbench-0.5:
tar xzvf sysbench-0.5.tar.gz
cd sysbench-0.5
chmod +x autogen.sh
./autogen.sh
./configure --with-mysql --with-mysql-includes=/usr/local/mysql
sql的复杂查询使用案列与技巧
百合不是茶
oracle sql 函数 数据分页 合并查询
本片博客使用的数据库表是oracle中的scott用户表;
------------------- 自然连接查询
查询 smith 的上司(两种方法)
&
深入学习Thread类
bijian1013
java thread 多线程 java多线程
一. 线程的名字
下面来看一下Thread类的name属性,它的类型是String。它其实就是线程的名字。在Thread类中,有String getName()和void setName(String)两个方法用来设置和获取这个属性的值。
同时,Thr
JSON串转换成Map以及如何转换到对应的数据类型
bijian1013
java fastjson net.sf.json
在实际开发中,难免会碰到JSON串转换成Map的情况,下面来看看这方面的实例。另外,由于fastjson只支持JDK1.5及以上版本,因此在JDK1.4的项目中可以采用net.sf.json来处理。
一.fastjson实例
JsonUtil.java
package com.study;
impor
【RPC框架HttpInvoker一】HttpInvoker:Spring自带RPC框架
bit1129
spring
HttpInvoker是Spring原生的RPC调用框架,HttpInvoker同Burlap和Hessian一样,提供了一致的服务Exporter以及客户端的服务代理工厂Bean,这篇文章主要是复制粘贴了Hessian与Spring集成一文,【RPC框架Hessian四】Hessian与Spring集成
在
【RPC框架Hessian二】Hessian 对象序列化和反序列化一文中
【Mahout二】基于Mahout CBayes算法的20newsgroup的脚本分析
bit1129
Mahout
#!/bin/bash
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information re
nginx三种获取用户真实ip的方法
ronin47
随着nginx的迅速崛起,越来越多公司将apache更换成nginx. 同时也越来越多人使用nginx作为负载均衡, 并且代理前面可能还加上了CDN加速,但是随之也遇到一个问题:nginx如何获取用户的真实IP地址,如果后端是apache,请跳转到<apache获取用户真实IP地址>,如果是后端真实服务器是nginx,那么继续往下看。
实例环境: 用户IP 120.22.11.11
java-判断二叉树是不是平衡
bylijinnan
java
参考了
http://zhedahht.blog.163.com/blog/static/25411174201142733927831/
但是用java来实现有一个问题。
由于Java无法像C那样“传递参数的地址,函数返回时能得到参数的值”,唯有新建一个辅助类:AuxClass
import ljn.help.*;
public class BalancedBTree {
BeanUtils.copyProperties VS PropertyUtils.copyProperties
诸葛不亮
PropertyUtils BeanUtils
BeanUtils.copyProperties VS PropertyUtils.copyProperties
作为两个bean属性copy的工具类,他们被广泛使用,同时也很容易误用,给人造成困然;比如:昨天发现同事在使用BeanUtils.copyProperties copy有integer类型属性的bean时,没有考虑到会将null转换为0,而后面的业
[金融与信息安全]最简单的数据结构最安全
comsci
数据结构
现在最流行的数据库的数据存储文件都具有复杂的文件头格式,用操作系统的记事本软件是无法正常浏览的,这样的情况会有什么问题呢?
从信息安全的角度来看,如果我们数据库系统仅仅把这种格式的数据文件做异地备份,如果相同版本的所有数据库管理系统都同时被攻击,那么
vi区段删除
Cwind
linux vi 区段删除
区段删除是编辑和分析一些冗长的配置文件或日志文件时比较常用的操作。简记下vi区段删除要点备忘。
vi概述
引文中并未将末行模式单独列为一种模式。单不单列并不重要,能区分命令模式与末行模式即可。
vi区段删除步骤:
1. 在末行模式下使用:set nu显示行号
非必须,随光标移动vi右下角也会显示行号,能够正确找到并记录删除开始行
清除tomcat缓存的方法总结
dashuaifu
tomcat 缓存
用tomcat容器,大家可能会发现这样的问题,修改jsp文件后,但用IE打开 依然是以前的Jsp的页面。
出现这种现象的原因主要是tomcat缓存的原因。
解决办法如下:
在jsp文件头加上
<meta http-equiv="Expires" content="0"> <meta http-equiv="kiben&qu
不要盲目的在项目中使用LESS CSS
dcj3sjt126com
Web less
如果你还不知道LESS CSS是什么东西,可以看一下这篇文章,是我一朋友写给新人看的《CSS——LESS》
不可否认,LESS CSS是个强大的工具,它弥补了css没有变量、无法运算等一些“先天缺陷”,但它似乎给我一种错觉,就是为了功能而实现功能。
比如它的引用功能
?
.rounded_corners{
[入门]更上一层楼
dcj3sjt126com
PHP yii2
更上一层楼
通篇阅读完整个“入门”部分,你就完成了一个完整 Yii 应用的创建。在此过程中你学到了如何实现一些常用功能,例如通过 HTML 表单从用户那获取数据,从数据库中获取数据并以分页形式显示。你还学到了如何通过 Gii 去自动生成代码。使用 Gii 生成代码把 Web 开发中多数繁杂的过程转化为仅仅填写几个表单就行。
本章将介绍一些有助于更好使用 Yii 的资源:
Apache HttpClient使用详解
eksliang
httpclient http协议
Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们再讨论),它不仅是客户端发送Http请求变得容易,而且也方便了开发人员测试接口(基于Http协议的),即提高了开发的效率,也方便提高代码的健壮性。因此熟练掌握HttpClient是很重要的必修内容,掌握HttpClient后,相信对于Http协议的了解会
zxing二维码扫描功能
gundumw100
android zxing
经常要用到二维码扫描功能
现给出示例代码
import com.google.zxing.WriterException;
import com.zxing.activity.CaptureActivity;
import com.zxing.encoding.EncodingHandler;
import android.app.Activity;
import an
纯HTML+CSS带说明的黄色导航菜单
ini
html Web html5 css hovertree
HoverTree带说明的CSS菜单:纯HTML+CSS结构链接带说明的黄色导航
在线体验效果:http://hovertree.com/texiao/css/1.htm代码如下,保存到HTML文件可以看到效果:
<!DOCTYPE html >
<html >
<head>
<title>HoverTree
fastjson初始化对性能的影响
kane_xie
fastjson 序列化
之前在项目中序列化是用thrift,性能一般,而且需要用编译器生成新的类,在序列化和反序列化的时候感觉很繁琐,因此想转到json阵营。对比了jackson,gson等框架之后,决定用fastjson,为什么呢,因为看名字感觉很快。。。
网上的说法:
fastjson 是一个性能很好的 Java 语言实现的 JSON 解析器和生成器,来自阿里巴巴的工程师开发。
基于Mybatis封装的增删改查实现通用自动化sql
mengqingyu
DAO
1.基于map或javaBean的增删改查可实现不写dao接口和实现类以及xml,有效的提高开发速度。
2.支持自定义注解包括主键生成、列重复验证、列名、表名等
3.支持批量插入、批量更新、批量删除
<bean id="dynamicSqlSessionTemplate" class="com.mqy.mybatis.support.Dynamic
js控制input输入框的方法封装(数字,中文,字母,浮点数等)
qifeifei
javascript js
在项目开发的时候,经常有一些输入框,控制输入的格式,而不是等输入好了再去检查格式,格式错了就报错,体验不好。 /** 数字,中文,字母,浮点数(+/-/.) 类型输入限制,只要在input标签上加上 jInput="number,chinese,alphabet,floating" 备注:floating属性只能单独用*/
funct
java 计时器应用
tangqi609567707
java timer
mport java.util.TimerTask; import java.util.Calendar; public class MyTask extends TimerTask { private static final int
erlang输出调用栈信息
wudixiaotie
erlang
在erlang otp的开发中,如果调用第三方的应用,会有有些错误会不打印栈信息,因为有可能第三方应用会catch然后输出自己的错误信息,所以对排查bug有很大的阻碍,这样就要求我们自己打印调用的栈信息。用这个函数:erlang:process_display (self (), backtrace).需要注意这个函数只会输出到标准错误输出。
也可以用这个函数:erlang:get_s