Note


  • Home

  • Archives

socketserver

Posted on 2016-10-19

TCP服务器端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env python

import socketserver
from time import ctime

HOST = ''
PORT = 21567
ADDR = (HOST, PORT)

class MyRequestHandler(socketserver.StreamRequestHandler):
def handle(self):
print('...connected from: ', self.client_address)
self.wfile.write('[%s] %s'.encode('utf-8') % (bytes(ctime(), 'utf-8'), self.rfile.readline()))

tcpServ = socketserver.TCPServer(ADDR, MyRequestHandler)
print('waiting for connection...')
tcpServ.serve_forever()

对handle进行了重写,原本为

1
def handle(self):pass

TCP客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/usr/bin/env python

from socket import *

HOST = 'localhost'
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST, PORT)

while True:
tcpCliSock = socket(AF_INET, SOCK_STREAM)
tcpCliSock.connect(ADDR)
data = input('> ')
if not data:
break
tcpCliSock.send(bytes(data + "\n", "utf-8"))
data = tcpCliSock.recv(BUFSIZ)
if not data:
break
print(data.strip().decode('utf-8'))
tcpCliSock.close()

在这个例子中,连接了服务器两次

Python网络编程

Posted on 2016-10-19

TCP时间戳服务器

在python3中,进行发送的数据都进行encode操作,转化为字符,而输出的部分都进行decode转化为string。

server_tcp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/usr/bin/env python

from socket import *
from time import ctime

HOST = ''
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST, PORT)

tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)

while True:
print('waiting for connection...')
tcpCliSock, addr = tcpSerSock.accept()
print('...connect from:', addr)

while True:
data = tcpCliSock.recv(BUFSIZ)
if not data:
break
response = '[%s] %s' % (bytes(ctime(), 'utf-8').decode('utf-8'), data.decode('utf-8'))
tcpCliSock.send(response.encode('utf-8'))

tcpCliSock.close()
tcpSerSock.close()

client_tcp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/env python

from socket import *

HOST = '127.0.0.1'
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST, PORT)

tcpCliSock = socket(AF_INET, SOCK_STREAM)
tcpCliSock.connect(ADDR)

# 用户无输入或者recv()方法调用失败,则跳出

while True:
data = input('> ')
if not data:
break
tcpCliSock.send(data.encode('utf-8'))
data = tcpCliSock.recv(BUFSIZ)
if not data:
break
print(data.decode('utf-8'))

tcpCliSock.close()

UDP时间戳服务器

server_udp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/env python

from socket import *
from time import ctime

HOST = ''
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST, PORT)

udpSerSock = socket(AF_INET, SOCK_DGRAM)
udpSerSock.bind(ADDR)

while True:
print('waiting for message...')
#接收到的数据和地址
data, addr = udpSerSock.recvfrom(BUFSIZ)
response = '[%s] %s' % (bytes(ctime(), 'utf-8').decode('utf-8'), data.decode('utf-8'))
udpSerSock.sendto(response.encode('utf-8'), addr)
print('...received from and returned to: ', addr)

udpSerSock.close()

client_udp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/env python

from socket import *

HOST = 'localhost'
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST, PORT)

udpCliSock = socket(AF_INET, SOCK_DGRAM)

while True:
data = input('> ')
if not data:
break
udpCliSock.sendto(data.encode('utf-8'), ADDR)
data, ADDR = udpCliSock.recvfrom(BUFSIZ)
if not data:
break
print(data.decode('utf-8'))

udpCliSock.close()

冒泡排序

Posted on 2016-09-21

冒泡学习笔记,原帖地址:https://github.com/damonare/Sorts

算法描述

冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

算法的描述和实现

  1. 比较相邻的元素。如果第一个比第二个大,就交换它们两个;
  2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
  3. 针对所有的元素重复以上的步骤,除了最后一个;
  4. 重复步骤1~3,直到排序完成。
  • JavaScript代码实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* Created by Dlala on 16/9/20.
*/
function bubbleSort(arr) {
var len = arr.length;
for (var i = 0; i < len; i++) {
for (var j = 0; j < len - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
var temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
return arr;
}

var arr = [3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48];

console.log(bubbleSort(arr));
  • 改进冒泡排序:
    设置一标志性变量pos,用于记录每趟排序中最后一次进行交换的位置。由于pos位置之后的记录均已交换到位,故在进行下一趟排序时只要扫描到pos位置即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* Created by Dlala on 16/9/20.
*/
function bubbleSort2(arr) {
var i = arr.length - 1; //初始位置
while (i > 0) {
var pos = 0;
for (var j = 0; j < i; j++) {
if (arr[j] > arr[j + 1]) {
var tmp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = tmp;
pos = j + 1;
}
}
i = pos;
}
return arr;
}

var arr = [3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48];
console.log(bubbleSort2(arr));

还有一种改进:

  • 传统冒泡排序中每一趟排序操作只能找到一个最大值或最小值,我们考虑利用在每趟排序中进行正向和反向两遍冒泡的方法一次可以得到两个最终值(最大者和最小者) , 从而使排序趟数几乎减少了一半。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
* Created by Dlala on 16/9/20.
*/
function bubbleSort3(arr) {
var low = 0;
var high = arr.length - 1;
var tmp, j = 0;
while (low < high) {
//正向冒泡,找最大值
for (j = low; j < high; j++) {
if (arr[j] > arr[j + 1]) {
tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
--high; //high前移
for (j = high; j > low; j--) {
if (arr[j] < arr[j - 1]) {
tmp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = tmp;
}
}
++low; //low后移
}
return arr;
}

var arr = [3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48];

console.log(bubbleSort3(arr));

新浪财经数据抓取

Posted on 2016-08-29

写了一个Python抓取新浪财经的脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#!/usr/bin/python
# -*- coding: utf-8 -*-
############################################
# @brief 新浪财经 http://hq.sinajs.cn/list=hk 行情编号,英文代码,中文名称
# @author dwk715@gmail.com
############################################
from urllib.request import urlopen
from bs4 import BeautifulSoup

listID = "00000"
count = 99999
with open('hk.txt', 'w') as f:

for x in range(count):
listID = int(listID) + 1
listID = str(listID).zfill(5)
url = "http://hq.sinajs.cn/list=hk" + listID
html = urlopen(url).read()
bsObj = BeautifulSoup(html, "html.parser", fromEncoding="GBK")
content = bsObj.get_text()
print(content.find(','))
if(content.find(',') != -1):
conntent = content.split('"')
conntent = conntent[1].split(',')
print(conntent)
f.write("HK" + listID)
f.write(',')
f.write(conntent[0])
f.write(',')
f.write(conntent[1])
f.write("\n")
else:
pass

脚本的运行效率不高,循环99999次用了2000s。

这里记录下写时遇到的几个坑:

  • zfill()

Python zfill() 方法返回指定长度的字符串,原字符串右对齐,前面填充0。

语法:

1
str.zfill(width)
  • bs4的get_text()

这个方法的返回值为str,我以前一直以为为list

  • 中文字符乱码
    这个问题是看这篇博文解决的,这里直接抄原画:

    • Beautiful Soup 会按顺序尝试不同的编码将你的文档转换为Unicode:
    • 可以通过fromEncoding参数传递编码类型给soup的构造器
    • 通过文档本身找到编码类型:例如XML的声明或者HTML文档http-equiv的META标签。 如果Beautiful Soup在文档中发现编码类型,它试着使用找到的类型转换文档。 但是,如果你明显的指定一个编码类型, 并且成功使用了编码:这时它会忽略任何它在文档中发现的编码类型。
    • 通过嗅探文件开头的一下数据,判断编码。如果编码类型可以被检测到, 它将是这些中的一个:UTF-*编码,EBCDIC或者ASCII。
    • 通过chardet库,嗅探编码,如果你安装了这个库。

      总的来说:

如果是网页标称为GB2312,但是部分字符用到了GBK的了,那么解决办法就是在调用BeautifulSoup,传递参数fromEncoding=”GBK”,即:

1
2
page = urllib2.build_opener().open(req).read()
soup = BeautifulSoup(page, fromEncoding=”GBK“)

如果是网页标称为GBK,但是部分字符用到了GB18030的了,那么解决办法就是在调用BeautifulSoup,传递参数fromEncoding=”GB18030″,即:

1
2
page = urllib2.build_opener().open(req).read()
soup = BeautifulSoup(page, fromEncoding=”GB18030“)

实际上由于GB18030从字符数上都涵盖了GB2312和GBK,所以如果是上述两种任意情况,即只要是中文字符出现乱码,不管是标称GB2312中用到了GBK,还是标称GBK中用到了GB18030,那么都直接传递GB18030,也是可以的,即:

1
soup = BeautifulSoup(page, fromEncoding=”GB18030“)

哦,对了,接下来会学习下多线程处理(笑)

JS调试

Posted on 2016-08-24

这两天学了阮一峰的Firebug控制台详解,记录下。

显示信息的命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html>

<head>
<title>常用console命令</title>
<meta charset="utf-8" ; http-equiv="Content-type" content="text/html" />
</head>

<body>
<script type="text/javascript">
console.log('hello');
console.info('信息');
console.error('错误');
console.warn('警告');
</script>
</body>

</html>

占位符

console上述的集中度支持printf的占位符格式,支持的占位符有:字符(%s)、整数(%d或%i)、浮点数(%f)和对象(%o)

1
console.log("%d年%d月%d日",2011,3,26);

信息分组

如果信息太多,可以分组显示,用到的方法是console.group()和console.groupEnd()。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html>

<head>
<title>信息分组</title>
<meta charset="utf-8" ; http-equiv="Content-Type" content="text/html" />
</head>

<body>
<script type="text/javascript">
console.group("group 1");
console.log("1.1");
console.log("1.2");
console.groupEnd();

console.group("group 2");
console.log("2.1");
console.log("2.2");
console.groupEnd();
</script>
</body>

</html>

查看对象的信息

console.dir()可以显示一个对象所有的属性和方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html>

<head>
<title>console_dir</title>
<meta charset="utf-8" ; http-equiv="Content-Type" content="text/html" />
</head>

<body>
<script type="text/javascript">
var info = {
blog: "http://dwk715.github.io",
QQ: 1030528946,
message: "D.va love you"
};
console.dir(info);
</script>
</body>

</html>

显示某个节点的内容

console.dirxml()用来显示网页的某个节点(node)所包含的html/xml代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html>

<head>
<title>console_dirxml</title>
<meta charset="utf-8" ; http-equiv="Content-Type" content="text/html" />
</head>

<body>
<div id="info">
<h3>blog: dwk715.github.io</h3>
<p>D.va love you</p>
</div>
<script type="text/javascript">
var info = document.getElementById('info');
console.dirxml(info);
</script>
</body>

</html>

判断变量是否是真

console.assert()用来判断一个表达式或变量是否为真。如果结果为否,则在控制台输出一条相应信息,并且抛出一个异常。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html>

<head>
<title>console_assert</title>
<meta charset="utf-8" ; http-equiv="Content-Type" content="http/text">
</head>

<body>
<script type="text/javascript">
var result = 0;
console.assert(result);
var year = 2016;
console.assert(year == 2018);
</script>
</body>

</html>

追踪函数的调用轨迹

console.trace()用来追踪函数的调用轨迹

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!DOCTYPE html>
<html>

<head>
<title>console_trace</title>
<meta charset="utf-8" ; http-equiv="Content-Type" content="http/text" />
</head>

<body>
<script type="text/javascript">
function add(a, b) {
console.trace();
return a + b;
}
var x = add3(1, 1)

function add3(a, b) {
return add2(a, b)
}

function add2(a, b) {
return add1(a, b)
}

function add1(a, b) {
return add(a, b)
}
</script>
</body>

</html>

计时功能

console.time()和console.timeEnd(),用来显示代码的运行时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html>

<head>
<title>console_time</title>
<meta charset="utf-8">
</head>

<body>
<script type="text/javascript">
console.time("控制台计时器一");
for (var i = 0; i < 1000; i++) {
for (var j = 0; j < 1000; j++) {}
}
console.timeEnd("控制台计时器一");
</script>
</body>

</html>

网络爬虫

Posted on 2016-08-17

网络爬虫的基本思想

  • 通过网站域名获取HTML数据
  • 根据目标信息解析数据
  • 存储目标信息
  • 如果有必要,移动到另一个网页重复以上过程

下面是一个简单的爬虫示例,主要运用了两个库

urllib和BeautifulSoup

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from urllib.request import urlopen
from urllib.error import HTTPError
from bs4 import BeautifulSoup


def getTitle(url):
try:
html = urlopen(url)
except HTTPError as e:
return None
try:
bsObj = BeautifulSoup(html.read())
title = bsObj.body.h1
except AttributeError as e:
return None
return title

title = getTitle("http://pythonscraping.com/pages/page1.html")
if title is None:
print("Title could not be found")
else:
print(title)

在这个例子中,使用了两个try保障了这个域名不为空,且包含h1这个元素

复杂HTML解析

BeautifulSoup

举个例子:

1
2
3
4
5
6
7
8
9
10
# BeautifulSoup的.get_text()会把超链接,段落和标签都清楚掉,只剩下一串不带标签的文字
from urllib.request import urlopen
from bs4 import BeautifulSoup


html = urlopen("http://www.pythonscraping.com/pages/warandpeace.html")
bsObj = BeautifulSoup(html)
nameList = bsObj.findAll("span", {"class": "green"})
for name in nameList:
print(name.get_text())

这个例子截取的网页中有一段小说的章节,其中人物名称部分的属性为class = "green"使用bs的findall将所有带class = "green"的元素找出来,再用.get_text()将人名过滤出来。

BeautifulSoup对象

  • Beautifulsoup

    上面例子中的bsObj

  • 标签tag对象

    Beautifulsoup对象通过findall()和find(),或者直接用bsObj.div.h1来获取一列对象或者一个对象

  • NavigableString

    用来表示标签的文字

  • Comment

    用来查找HTML文档的注释标签,like this <!-- 123 -->

导航树

导航树(Navigating tree)通过标签在闻到中的位置来查找标签。(感觉上就是DOM的树结构了)

处理子标签和其他后代标签(虐子)

在BeautifulSoup库中,孩子(child)和后代(descendant)有显著的不同:子标签就是一个夫标签的下一级,而后代标签是一个夫标签下面所有级别的标签。因此可以说,所有子标签都是后代标签,但不是所有的后代标签都是子标签。

一般情况下BeautifulSoup函数总是处理当前标签的后代标签。例如,bsObj.body.h1选择了body标签后代里的第一个h1标签,而不会去找body外面的标签。

于此类似,bsObj.div.findAll("img")会找出文档中第一个div标签,然后获取这个div后代里的所有img标签列表。

python网络爬虫练习

Posted on 2016-08-17

今天完成了一个小爬虫练习,将一个overwatch的壁纸分享上的图片爬了下来并保存在本地

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 抓取网页中的图片到本地
# 1. 抓取网页
# 2. 获取图片地址
# 3. 抓取图片内容并保存到本地
# 抓取的图片为ow
from urllib import request
import re
req = request.urlopen('http://ow.duowan.com/1604/324398538441.html')
buf = req.read()
buf = buf.decode('UTF-8')
# print(buf)
listUrl = re.findall(r'http://img.+.jpg', buf)
# print(listUrl)
i = 0

for url in listUrl:
f = open(str(i) + '.jpg', 'wb')
req = request.urlopen(url)
buf = req.read()
f.write(buf)
i += 1

在写的过程中遇到几个坑,记录一下:

  • python3已经取消了urllib2,改为from urllib import request,下面的方法也跟着改就好
  • 爬下来的数据需要转码decode('UTF-8')
  • 在保存图片文件时应该使用wb方式,二进制方式写数据

接下来会系统学习下网络爬虫,基于python3(笑)

python正则表达式学习

Posted on 2016-08-16

正则表达式基础

Python的正则表达式依赖于re模块:

1
import re

基本结构为:
string –> Pattern –> Match –>result

简单示例:

1
2
3
4
5
6
import re
str1 = 'Dlala is dlala'
pa = re.compile(r'Dlala') #r表示原字符串
ma = pa.match(str1)
result = ma.group()
print result

另一个基本示例:

1
2
3
4
5
import re
str1 = 'Dlala is dlala'
ma = re.match(r'Dlala', str1)
result = ma.group()
print result

正则表达式语法(匹配单个字符):

字符 匹配 示例
. 匹配任意字符(除\n外) re.match(r’.’,’d’)
[…] 匹配字符集 re.match(r’[a-zA-Z0-9]’,’d’)
\d / \D 匹配数字 / 非数字 re.match(r’\d’, ‘0’)
\s / \S 匹配空白 / 非空白字符 re.match(r’\s’, ‘ ‘)
\w / \W 匹配单词字符[a-zA-Z0-9] / 非单词字符 re.match(r’\w’, ‘d’)

正则表达式语法(匹配多个字符):

字符 匹配 示例
* 匹配前一个字符0到无限次 re.match(r’[A-Z][a-z]*’, ‘Dlala123’)
+ 匹配前一个字符1到无限次 ma = re.match(r’[_a-zA-Z]+[\w]*’, ‘_Dlala123’)
? 匹配前一个字符0次或1次 ma = re.match(r’[1-9]?[0-9]*’,’76’)
{m} / {m,n} 匹配一个字符m次 / m到n次 ma = re.match(r’[0-9A-Za-z]{6,9}@mail.com’, ‘dwk715@mail.com’)
*? / +? / ?? 匹配模式变为非贪婪(尽可能减少匹配字符) 0次,1次,0次

Python re模块

re模块有很多个方法,下面介绍一下:

search(pattern, string, flags=0)
在一个字符串中查找匹配

类似于字符串的find

1
2
3
4
import re
str1 = "we have 1000 seed"
info = re.search(r'\d+', str1)
print(info.group()) #1000

findall(pattern, string, flags=0)
找到匹配,返回所有匹配部分的列表

1
2
3
4
5
import re
str1 = "javascript=80, python=88, html=100"
info = re.findall(r'\d+', str1)
print(info)
print('sum is', sum(int(x) for x in info))

1
2
3
4
5
6
sub(pattern, repl. string, count=0, flags=0)
#pattern 正则表达式
#repl 替换的字符串或者函数表达式
#string 被替换的字符串
#count 替换次数限制
#flags

将字符串中匹配正则表达式的部分替换为其他值

1
2
3
4
import re
str1 = 'Dlala is 22 years old'
info = re.sub(r'\d+', '23', str1)
print(info)
1
2
3
4
5
6
7
8
9
import re
str1 = 'Dlala is 22 years old'
def addOne(match):
val = match.group()
age = int(val) + 1
return str(age)

#这里的match是正则表达式匹配到的部分
print(re.sub(r'\d+', addOne, str1))

1
2
split(pattern, string, maxsplit=0, flags=0)
# maxsplit为分割的次数
1
2
3
4
import re
str1 = "I'm learning:python, javascript, html and css"
info = re.split(r':|, | and ', str1)
print(info)

awk

Posted on 2016-08-12

老样子,在Mac OS还是改下awk的版本为gnu awk

1
2
3
brew install coreutils
brew install gawk
alias awk=gawk

yum downloadonly

Posted on 2016-08-10

Issue

  • How do I use yum to download a package withoout installing it?

Resolution

Yumdownloader

if downloading a installed package, “yumdownloader” is useful.

1. Install the yum-utils package:

1
# yum install yum-utils

2. Run the command followed by the desired package:

1
# yumdownloader <package>

Note:

  • The package is saved in the current working directly by default; use the –destdir option to specify an alternate location.
  • Be sure to add –resolve if you need to download dependencies.

install package

1
2
3
4
5
#rpm -ivh <package>
-i : install 的意思
-v : 察看更細部的安裝資訊畫面
-h : 以安裝資訊列顯示安裝進度
-Uvh : 後面接的軟體即使沒有安裝過,則系統將予以直接安裝; 若後面接的軟體有安裝過舊版,則系統自動更新至新版;
123

Dlala

编程是不可能离开Google的( ̄^ ̄)ゞ

26 posts
18 tags
© 2018 Dlala
Powered by Hexo
|
Theme — NexT.Muse v5.1.4