分类 Python 下的文章

PolicyServer

最近做一个项目需要用到websocket,但是目前ie9及之前的版本都不支持,github上面出现了用flash模拟websocket的开源项目,由于使用flash时,flash是有权限限制的(这应该是为了安全性考虑),xmlsocket://会先访问843端口,获取授权文件。于是自己用python写了个,该程序依赖tornado库。http://inote.github.com/PolicyServer/

SmartMarkdown插件bug

bug描述

SmartMarkdown是Sublime Text2的一个插件,该插件提供了smart table的功能,该功能在只有ascii字符的时候很完美,但当内容中出现中文,中文标点的时候就会产生错位,这是因为中文在屏幕上的显示占了两倍的英文所占有的位置。

bug修复

由于该插件里面计算的时候是按照字符的长度来计算的,所以他把中文字符串的长度也是计算为1的。我们要做的就是把非ascii字符串替换为两个占位字符,然后计算长度。找到插件目录下的table.py

# 21行添加
NONE_ASCII_PATTERN = re.compile(r'[^\x00-\xff]')
# 124行修改为
new_row.append(col + " " * (cols_length[i] - len(NONE_ASCII_PATTERN.sub('  ',col))))
# 163行修改为
col_len = len(NONE_ASCII_PATTERN.sub('  ', col))

修改过的文件:下载

利用百度地图API拆分纯真IP数据库地址

导出txt,并转码

利用安装后的ip.exe导出txt文件,由于python处理gbk中文的时候会有些问题,所以我们直接选个编辑器打开之后,再以utf-8的编码保存就可以了。

提取所有地址

由于我们需要通过百度地图的API一个地址一个地址的查询,所以去除重复的地址可以减少我们的查询量。

# coding: utf-8
# python的去重方法很多,这里我们选用set类型
with open('ipdata.txt', 'r', encoding='utf-8') as handle:
    regex = re.compile(' +')
    addrs = set([])
    for line in handle:
        if line.strip() != '':
            address = regex.split(line.strip())[2]
            addrs.add(address)
    # addrs 就是我们过滤之后的所有地址了

上面我们已经过滤出所有的地址了,接下来就是使用百度的API来拆解这些地址。

import re, urllib, time, json
from urllib import parse, request

with open('ipdata.txt', 'r', encoding='utf-8') as handle:
    regex = re.compile(' +')
    addrs = set([])
    for line in handle:
        if line.strip() != '':
            address = regex.split(line.strip())[2]
            addrs.add(address)

    url = 'http://api.map.baidu.com/geocoder?output=json&key=你的API key'

    wh = open('address/list.txt', 'w', encoding="utf-8")
    for addr in addrs:
        addr_x = ''
        url_x = url + '&address=' + parse.quote(addr)
        # time.sleep(3)
        req = request.urlopen(url_x)
        res = req.read().decode()

        data = json.loads(res)

        if data['result']:
            location = str(data['result']['location']['lat']) + ', ' + str(data['result']['location']['lng'])
            url_x = url + '&location=' + parse.quote(location)

            req = request.urlopen(url_x)
            res = req.read().decode()

            data = json.loads(res)
            if data['result']:
                component = data['result']['addressComponent']
                addr_x = component['province'] + ' ' + component['city'] + ' ' + component['district']
        wh.write(addr + '\t' + addr_x + '\n')
    wh.close()

未完待续...

wxpython练手

学习wxpython的练手软件,写的比较简单,名为扫描,实际上每次只能扫描一个端口。

PS:py2exe打包的程序伤不起啊,小小的一个程序,依赖库什么放进去竟有20多M。
setup里面设置的icon_resources居然没成功,不知道是不是哪儿写错了。

源码:下载

python http server

前端调试的时候,有的时候需要网络环境,哥对bat不懂,自己就瞎凑了个代码出来,以下代码需要python3.x的支持。

@echo off
set port=8080
if not ""%1"" equ """" set port=%1
python -m http.server %port% | explorer http://localhost:%port%
@echo on

python中的那些else

python与其他语言不同的是,else不仅可以和if搭配,它还可以跟其他的逻辑语句一起使用;if/else这里就不在记录。

while/else for/else

# 只有当循环正常执行完的时候,才会执行else中的语句,如果循环语句被break的时候,将不会执行else中的语句
for i in range(1, 11):
	if i == 8:
		break
	print(i, end = ',')
else:
	print(11)
# 1,2,3,4,5,6,7,

for i in range(1, 11):
	print(i, end = ',')
else:
	print(11)
# 1,2,3,4,5,6,7,8,9,10,11

try/except/else/finally

try:
	raise(RuntimeError, 'force issue')
except:
	# 抛出错误时执行
	print(1)
else:
	# 在不抛出错误的情况下执行
	print(2)
finally:
	# 不管有没有抛出错误都执行
	print(3)

python杂记2

判断是否为数字

isdigit()的话,里面不能有小数点。

def is_number(s):
    try:
        n=str(float(s))
        if n == "nan" or n=="inf" or n=="-inf" : return False
    except ValueError:
        return False
    return True

切分list

def chunks(l, n):
    return [l[i: i + n] for i in range(0, len(l), n)]

字符串数字取整

直接用int会报错。

str = "545.2222"
print(int(float(str)))

合并字典

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}

# python2.x
z = dict(x.items() + y.items())
# python3.x
z = dict(list(x.items()) + list(y.items()))

# another way
z = dict(x, **y)

os.path.join的坑

如果路径中有绝对路径,则前面的所有路径都会被抛弃

《编程珠玑》学习笔记

书是买了好久,一直没心情,到今天才拿起来看,算法使用python实现。

位图排序

import random
# 产生一组随机数
unsorted = [random.randint(1, 19) for i in range(7)]

print(unsorted)
# 初始化一个向量组
bits = [0] * 20
# 储存排序后的结果
hsorted = []
# 对号入座
for i in unsorted:
	bits[i] = 1
for n, m in enumerate(bits):
	if m == 1:
		hsorted.append(n)

print(hsorted)

二分法查找

lis = [0,1,2,3,4,5,6,7,8]

search = 7.5

def binarySearch(lis, search):
	low = 0
	high = len(lis) - 1
	while low <= high:
		#mid = (low + high) // 2
		mid = (low + high) >> 1
		if search < lis[mid]:
			high = mid - 1
		elif search > lis[mid]:
			low = mid + 1
		elif search == lis[mid]:
			return mid
	if low > len(lis) - 1 or high < 0:
		return -1
	return (high, low)

print(binarySearch(lis, search))

变量的作用域

php的变量作用范围

$str = 'something';
function infunction() {
    echo $str; //报错
}
function infunc() {
    $str = 'one two three';
    echo $str; //one two three
}
echo $str; //something
//不搭嘎啊

javascript变量作用范围

var str = 'something';
function infunction() {
    console.log(str); //something
    str = 'one two three';
}
console.log(str); //one two three
//想function里面的变量私有化,则需要var来定义

python变量作用范围

str = 'something';
def infunction():
    print(str) #something
def infunc():
    print(str) #报错
    str = 'one two three'
#在def中不对外部变量赋值时,外部变量可直接使用(global)
#一旦在def中对变量复制,def中的变量将会私有化(locale)

位运算

基本概念

  • 左移 <<
    右边空位补0,其值相当于x2。
  • 右移 >>
    如果为正数左边空位补0,如果为负数则可能补0或补1(取决于所使用的计算机系统)。
  • 按位与 &
    两个都为1则为1
  • 按位或 |
    其中一个为1则为1
  • 按位异或 ^
    “半加”,不同的为1,相同的为0
  • 取反 ~
    ~1 = 0, ~0 = 1 涉及补码的算法:
    1. 正数的补码与原码相同
    2. 负数的补码是对其原码逐位取反,但符号位(第一位)除外;然后整个数加1。

常用算法

判断奇偶性

lambda x : x & 1

取二进制数的第k位

lambda x, k : x >> k & 1

二进制数k位清0

lambda x : x & ~ (1 << k)

二进制数k位置1

lambda x : x | (1 << k)

求平均值

lambda x, y : (x & y) + ((x ^ y) >> 1)

判断是否为2的幂

lambda x : ((x & (x-1)) == 0) && (x != 0)

交换两整数

a, b = 3, 4
a = a ^ b
b = b ^ a
a = a ^ b
print(a, b) #4 3

python多线程读取文件

网上只有多进程,有木有?理解和书写代码花了一天的时间,有木有?

多线程分块读取

# -*- coding: utf-8 -*-
import os,time
import threading

rlock = threading.RLock()
curPosition = 0

class Reader(threading.Thread):
    def __init__(self, res):
        self.res = res
        super(Reader, self).__init__()
    def run(self):
        global curPosition
        fstream = open(self.res.fileName, 'r')
        while True:
            #锁定共享资源
            rlock.acquire()
            startPosition = curPosition
            curPosition = endPosition = (startPosition + self.res.blockSize) if (startPosition + self.res.blockSize) < self.res.fileSize else self.res.fileSize
            #释放共享资源
            rlock.release()
            if startPosition == self.res.fileSize:
                break
            elif startPosition != 0:
                fstream.seek(startPosition)
                fstream.readline()
            pos = fstream.tell()
            while pos < endPosition:
                line = fstream.readline()
                #处理line
                #print(line.strip())
                pos = fstream.tell()
        fstream.close()

class Resource(object):
    def __init__(self, fileName):
        self.fileName = fileName
        #分块大小
        self.blockSize = 100000000
        self.getFileSize()
    #计算文件大小
    def getFileSize(self):
        fstream = open(self.fileName, 'r')
        fstream.seek(0, os.SEEK_END)
        self.fileSize = fstream.tell()
        fstream.close()

if __name__ == '__main__':
    starttime = time.clock()
    #线程数
    threadNum = 4
    #文件
    fileName = 'IPData.txt';
    res = Resource(fileName)
    threads = []
    #初始化线程
    for i in range(threadNum):
        rdr = Reader(res)
        threads.append(rdr)
    #开始线程
    for i in range(threadNum):
        threads[i].start()
    #结束线程
    for i in range(threadNum):
        threads[i].join()

    print(time.clock() - starttime)

多线程按行读取

#在上面的代码中使用open(file, 'r')产生的句柄每次在线程锁里面pop()就好了。

python之排序算法

快速排序

取一个元素,剩余元素与这个元素比较,小的放左边,大的放右边,依此循环嵌套,以下是实现的代码:

lis = [18,2,4,54,64,56,77]
def quicksort(lis):
	return [] if lis == [] else quicksort([x for x in lis[1:] if x < lis[0]]) + [lis[0]] + quicksort([x for x in lis[1:] if x >= lis[0]])
print(quicksort(lis))

正则杂记

验证手机号码

中国移动号段 1340-1348 135 136 137 138 139 150 151 152 157 158 159 187 188 147
中国联通号段 130 131 132 155 156 185 186 145
中国电信号段 133 1349 153 180 189
其他 181 182 183 184
^(13[0-9]|15[0-9]|14[0-9]|18[0-9])\d{8}$
^(1[3-5][0-9]|18[0-9])\d{8}$
^(1[3-58])\d{9}$

验证邮箱

^\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,4}$

验证日期

^((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]|[2-9]\d)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29-))$

验证时间

格式:时:分:秒

^([01]?\d|2[0-3]):[0-5]?\d:[0-5]?\d$

验证url

^\b(((https?|ftp):\/\/)?[-a-z0-9]+(\.[-a-z0-9]+)*\.(?:com|edu|gov|int|mil|net|org|biz|info|name|museum|coop|aero|[a-z][a-z]|((25[0-5])|(2[0-4]\d)|(1\d\d)|([1-9]\d)|\d))\b(\/[-a-z0-9_:\@&?=+,.!\/~%\$]*)?)$

环视

以前一直没明白正则的环视的使用环境,网上的那些例子不用环视也能写出来,而且更容易理解。其实,在需要匹配的字符串有长度限制的时候,而且有其他的特殊要求的时候,用环视能很好的解决问题。这样说,还太抽象了,下面看例子:

#有待更新

一些注册表单会用到的正则

用户名(允许字母、数字、下划线、减号、中文)

^[A-Za-z0-9_\-\u4e00-\u9fa5]+$
^[A-Za-z0-9_\-\x{4e00}-\x{9fa5}]+$

真实姓名(允许字母、中文)

^[A-Za-z\u4e00-\u9fa5]+$    // js
^[A-Za-z\x{4e00}-\x{9fa5}]+$    // php

http及https的url

^http[s]?:\/\/([\w-]+\.)+[\w-]+([\w-./?%&=]*)?$

IP v4,下面把四个展开写是为了看起来比较直观,其实可以写的更短一点。

^(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)$

验证子网掩码

^(((255\.){3}(255|254|252|248|240|224|192|128|0+))|((255\.){2}(255|254|252|248|240|224|192|128|0+)\.0)|((255\.)(255|254|252|248|240|224|192|128|0+)(\.0+){2})|((255|254|252|248|240|224|192|128|0+)(\.0+){3}))$

lxml 加 beautifulsoup with 多线程(Snail)

抓取的时候,去获取网页中指定的内容,最基本的办法就是使用正则获取,但要是要处理的网站多了,写正则岂不写死。于是哥就写了个类,看代码:

蜗牛号基类

# -*- coding: utf-8 -*-
import threading, Queue
import urllib2, cookielib
from lxml.html.soupparser import fromstring

class Snail(threading.Thread):
	def __init__(self , *argv):
		self.buildBrowser(*argv)
		super(Snail, self).__init__()
	def buildBrowser(self, *argv):
		self.cookie = cookielib.CookieJar()
		opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cookie))
		opener.addheaders = []
		opener.addheaders.append(('User-Agent', 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.904.0 Safari/535.7'))
		opener.addheaders.append(('Accept', '*/*'))
		opener.addheaders = opener.addheaders + [t for t in argv]
		urllib2.install_opener(opener)
	def parse(self, link, data = None):
		content = self.handle(link, data).read()
		tree = fromstring(content)
		return tree
	def handle(self, link, data = None):
		return urllib2.urlopen(urllib2.Request(link, data))
	def save(self):
		pass
snail = Snail(('Cookie','这边可以自己填写'))

需要lxml模块支持,可以到 http://lxml.de/ 下载,centos下的安装方法:

yum -y install libxml2-dev libxslt-devel
cd /usr/local/src
wget http://lxml.de/files/lxml-2.3.2.tgz
tar vzxf lxml-2.3.2.tgz
cd lxml-2.3.2
python setup.py install

cd ../
wget http://www.crummy.com/software/BeautifulSoup/download/3.x/BeautifulSoup-3.2.0.tar.gz
tar vzxf BeautifulSoup-3.2.0.tar.gz
cd BeautifulSoup-3.2.0
python setup.py install

基类的使用实例

线程锁rlock

# -*- coding: utf-8 -*-
from Snail import Snail
import threading

rlock = threading.RLock()
class Mphone(Snail):
	def __init__(self):
		super(Snail, self).__init__()
	def process(self, numhead):
		#做点实际处理的事情
		pass
	def run(self):
		while True:
			rlock.acquire()
			#线程锁锁定资源的时候,取值
			rlock.release()
			#可以在某个特定条件下 break 掉循环
			self.process(numhead)
if __name__ == '__main__':
	threadnum = 4
	threads = []
	for i in range(threadnum):
		mphone = Mphone()
		threads.append(mphone)
	for i in range(threadnum):
		threads[i].start()
	for i in range(threadnum):
		threads[i].join()

可能会遇到的一些问题

TypeError: cannot concatenate 'str' and 'NoneType' objects
#解决办法
unicode('这边是要解析的字符串', 'utf-8', errors='ignore')