python学习更近一步

news/2024/11/7 22:44:32/

先从以下的库入手吧!

import requests                                  #能进行网页请求
from lxml import etree                       #解析网页的方法之一,涉及的知识见下文(一)
from multiprocessing import Pool     #相关知识,见下文(二)
import time                                        #引入time模块,扩充见下文(三)
import datetime                                 #引入datetime模块,扩充见下文(四)
from bs4 import BeautifulSoup        #解析网页方法之二
import json                                        #为了编解json代码而引进,涉及的知识见下文(五)

import os                                          #涉及的知识见下文(六)
import re                                          #解析网页方法之三:正则表达式。

import xlwt                                       #工作中需要导出的数据为Excel格式,就要使用xlwt 模块,涉及的知识见下文(七)

(一)网页解析lxml:
》》》由于使用的是Xpath语法,所以首先要了解Xpath语法:
1. 节点关系:
(1)父:每个元素以及属性都有一个父,在下面的例子中,book 元素是 title、author、year 以及 price 元素的父:
<book>
  <title>Harry Potter</title>
  <author>J K. Rowling</author>
  <year>2005</year>
  <price>29.99</price>
</book>

(2)子:元素节点可有零个、一个或多个子,在上述的例子中,title、author、year 以及 price 元素都是 book 元素的子。
(3)同胞:拥有相同的父的节点,在上述的例子中,title、author、year 以及 price 元素都是同胞。
(4)先辈:某节点的父、父的父,等等,在下面的例子中,title 元素的先辈是 book 元素和 bookstore 元素:
<bookstore>

<book>
  <title>Harry Potter</title>
  <author>J K. Rowling</author>
  <year>2005</year>
  <price>29.99</price>
</book>

</bookstore>
(5)后代:某个节点的子,子的子,等等,在上述的例子中,bookstore 的后代是 book、title、author、year 以及 price 元素。

2.选取节点:XPath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的。
下面列出了最有用的路径表达式:

表达式描述
nodename选取此节点的所有子节点。
/从根节点(在自己上面没有更高一级的节点,自己这个节点就叫根节点)选取。
//从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
.选取当前节点。
..选取当前节点的父节点。
@选取属性。

实例:
在下面的表格中,已列出了一些路径表达式以及表达式的结果:

路径表达式结果
bookstore选取 bookstore 元素的所有子节点。
/bookstore        选取根元素 bookstore。注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!
bookstore/book        选取属于 bookstore 的子元素的所有 book 元素。
//book         选取所有 book 子元素,而不管它们在文档中的位置。
bookstore//book         选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。
//@lang选取名为 lang 的所有属性。

注意:

bookstore/book        选取属于 bookstore 的子元素的所有 book 元素
bookstore//book         选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。



3.谓语:
谓语用来查找某个特定的节点或者包含某个指定的值的节点,谓语被嵌在方括号中。
实例:
在下面的表格中,列出了带有谓语的一些路径表达式,以及表达式的结果:

路径表达式结果
/bookstore/book[1]选取属于 bookstore 子元素的第一个 book 元素。
/bookstore/book[last()]选取属于 bookstore 子元素的最后一个 book 元素。
/bookstore/book[last()-1]选取属于 bookstore 子元素的倒数第二个 book 元素。
/bookstore/book[position()<3]选取最前面的两个属于 bookstore 元素的子元素的 book 元素
//title[@lang]选取所有拥有名为 lang 的属性的 title 元素。
//title[@lang=’eng’]选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。
 
/bookstore/book[price>35.00]选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。
/bookstore/book[price>35.00]/title选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。





4.选取未知节点:
XPath 通配符可用来选取未知的 XML 元素。

通配符         描述
*匹配任何元素节点。
@*匹配任何属性节点。
node()匹配任何类型的节点。


实例:
在下面的表格中,列出了一些路径表达式,以及这些表达式的结果:

路径表达式结果
//*选取文档中的所有元素。
/bookstore/*选取 bookstore 元素的所有子元素。
//title[@*]选取所有带有属性的 title 元素。



5.选取若干路径:
通过在路径表达式中使用“|”运算符,您可以选取若干个路径。
实例:
在下面的表格中,列出了一些路径表达式,以及这些表达式的结果:

路径表达式结果
//book/title | //book/price        选取 book 元素的所有 title 和 price 元素。
//title | //price选取文档中的所有 title 和 price 元素。
/bookstore/book/title | //price选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。



6.XPath 运算符:
下面列出了可用在 XPath 表达式中的运算符:

运算符描述     实例返回值
|  计算两个节点集返回所有拥有 book 和 cd 元素的节点集//book | //cd        返回所有拥有 book 和 cd 元素的节点集(这一点不懂)
+加法6+410
减法6-42
乘法乘法6*424
div除法8div42
=等于price=9.80        如果 price 是 9.80,则返回 true。如果 price 是 9.90,则返回 false。
!=不等于  price!=9.80        如果 price 是 9.90,则返回 true。如果 price 是 9.80,则返回 false。
<小于  price<9.80如果 price 是 9.00,则返回 true。如果 price 是 9.90,则返回 false。
<=小于或等于  price<=9.80      如果 price 是 9.00,则返回 true。如果 price 是 9.90,则返回 false。
>大于   price>9.80        如果 price 是 9.90,则返回 true。如果 price 是 9.80,则返回 false。
>=大于或等于  price>=9.80      如果 price 是 9.90,则返回 true。如果 price 是 9.70,则返回 false。
or  price>9.80 or  price<9.70如果 price 是 9.80,则返回 true。如果 price 是 9.50,则返回 false。
and   price>9.00 and price<9.90如果 price 是 9.80,则返回 true。如果 price 是 8.50,则返回 false。
mod  计算除法的余数   5 mod   21


由此,初步了解了Xpath语法后,终于迎来:
》》》lxml用法:


1.初步使用:
首先利用它来解析 HTML 代码(复制粘贴网络里的,只为了更好理解,没有实际操作):
from lxml import etree
text = '''
<div>
    <ul>
         <li class="item-0"><a href="link1.html">first item</a></li>
         <li class="item-1"><a href="link2.html">second item</a></li>
         <li class="item-inactive"><a href="link3.html">third item</a></li>
         <li class="item-1"><a href="link4.html">fourth item</a></li>
         <li class="item-0"><a href="link5.html">fifth item</a>
     </ul>
</div>
'''
html = etree.HTML(text)            #etree.HTML():构造了一个XPath解析对象并对HTML文本进行自动修正
result = etree.tostring(html)       #etree.tostring():输出修正后的结果,但结果是bytes类型
print(result.decode('utf-8'))         #这里需要利用decode()方法将其转成str类型


其中,应该注意到最后一个 li 标签的尾标签被删掉了,是不闭合的。然后使用 lxml 的 etree 库,利用 etree.HTML 初始化(调用HTML类进行初始化,这样就成功构造了一个XPath解析对象),再将其打印出来(之前的方法也遇到打印哟),就能体现 lxml 自动修正 html 代码的功能 。
所以输出结果是这样的:
<html><body>
<div>
    <ul>
         <li class="item-0"><a href="link1.html">first item</a></li>
         <li class="item-1"><a href="link2.html">second item</a></li>
         <li class="item-inactive"><a href="link3.html">third item</a></li>
         <li class="item-1"><a href="link4.html">fourth item</a></li>
         <li class="item-0"><a href="link5.html">fifth item</a></li>
</ul>
</div>

</body></html>


不仅补全了 li 标签,还添加了 body,html 标签。

2.文件读取:
除了直接读取字符串,还支持从文件读取内容。比如新建一个文件叫做 hello.html,内容为:
<div>
    <ul>
         <li class="item-0"><a href="link1.html">first item</a></li>
         <li class="item-1"><a href="link2.html">second item</a></li>
         <li class="item-inactive"><a href="link3.html"><span class="bold">third item</span></a></li>
         <li class="item-1"><a href="link4.html">fourth item</a></li>
         <li class="item-0"><a href="link5.html">fifth item</a></li>
     </ul>
</div>
利用 parse 方法来读取文件:
from lxml import etree
html = etree.parse('hello.html')
result = etree.tostring(html, pretty_print=True)
print(result)
同样可以得到相同的结果。
3.XPath实例测试敲黑板的重点
依然以该程序为例:
<div>
    <ul>
         <li class="item-0"><a href="link1.html">first item</a></li>
         <li class="item-1"><a href="link2.html">second item</a></li>
         <li class="item-inactive"><a href="link3.html"><span class="bold">third item</span></a></li>
         <li class="item-1"><a href="link4.html">fourth item</a></li>
         <li class="item-0"><a href="link5.html">fifth item</a></li>
     </ul>
</div>

(1)获取所有的 <li> 标签:
from lxml import etree
html = etree.parse('hello.html')
print type(html)
result = html.xpath('//li')
print result
print len(result)
print type(result)
print type(result[0])
运行结果:
<type 'lxml.etree._ElementTree'>
[<Element li at 0x1014e0e18>, <Element li at 0x1014e0ef0>, <Element li at 0x1014e0f38>, <Element li at 0x1014e0f80>, <Element li at 0x1014e0fc8>]
5
<type 'list'>
<type 'lxml.etree._Element'>
可见,etree.parse 的类型是 ElementTree,通过调用 xpath 以后,得到了一个列表,包含了 5 个 <li> 元素,每个元素都是 Element 类型(不清楚这个代码在爬虫代码中的具体意义
(2)获取 <li> 标签的所有 class:
result = html.xpath('//li/@class')          
print result
运行结果:
['item-0', 'item-1', 'item-inactive', 'item-1', 'item-0']
(3)获取 <li> 标签下 href 为 link1.html 的 <a> 标签:
result = html.xpath('//li/a[@href="link1.html"]')
(4)获取 <li> 标签下的所有 <span> 标签:
注意这么写是不对的:
result = html.xpath('//li/span')
因为 / 是用来获取子元素的,而 <span> 并不是 <li> 的子元素,所以,要用双斜杠:
result = html.xpath('//li//span')
print result
运行结果:
['blod']
(5)获取 <li> 标签下的所有 class,不包括 <li>:
result = html.xpath('//li/a//@class')
(6)获取最后一个 <li> 的 <a> 的 href:
result = html.xpath('//li[last()]/a/@href')
print result
运行结果:
['link5.html']
(7)获取倒数第二个元素的内容:
result = html.xpath('//li[last()-1]/a')
print result[0].text      
运行结果:
fourth item
(8)获取 class 为 bold 的标签名:
result = html.xpath('//*[@class="bold"]')
print result[0].tag      
运行结果:
span



(二)多进程与多线程:

1.区别:    “进程是资源分配的最小单位,线程是CPU调度的最小单位”。

对比维度多进程多线程     总结
数据共享、同步数据共享复杂,同步简单  数据共享简单,同步复杂各有优劣
内存、CPU占用内存多,切换复杂,CPU利用率低占用内存少,切换简单,CPU利用率高线程占优
创建、销毁、切换  复杂,速度慢  简单,速度快线程占优
编程、调试编程简单,调试简单编程复杂,调试复杂进程占优
可靠性进程间不会互相影响一个线程挂掉将导致整个进程挂掉进程占优
分布式适用于多核、多机,扩展到多台机器简单适用于多核进程占优


百度到:进程和线程可以类比为火车和车厢:
线程在进程下行进(单纯的车厢无法运行)
一个进程可以包含多个线程(一辆火车可以有多个车厢)
不同进程间数据很难共享(一辆火车上的乘客很难换到另外一辆火车,比如站点换乘)
同一进程下不同线程间数据很易共享(A车厢换到B车厢很容易)
进程要比线程消耗更多的计算机资源(采用多列火车相比多个车厢更耗资源)
进程间不会相互影响,一个线程挂掉将导致整个进程挂掉(一列火车不会影响到另外一列火车,但是如果一列火车上中间的一节车厢着火了,将影响到该趟火车的所有车厢)
进程可以拓展到多机,进程最多适合多核(不同火车可以开在多个轨道上,同一火车的车厢不能在行进的不同的轨道上)
进程使用的内存地址可以上锁,即一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。(比如火车上的洗手间)-”互斥锁(mutex)”
进程使用的内存地址可以限定使用量(比如火车上的餐厅,最多只允许多少人进入,如果满了需要在门口等,等有人出来了才能进去)-“信号量(semaphore)”

2.多进程学习(官方语言:multiprocessing支持子进程、通信和共享数据、执行不同形式的同步,提供了Process、Queue、Pipe、Lock等组件):

(1)Process:

》》》基本使用:
在multiprocessing中,每一个进程都用一个Process类来表示:
Process([group [, target [, name [, args [, kwargs]]]]])
其中:
target表示调用对象,可以传入方法的名字 
args表示被调用对象的位置参数元组,比如target是函数a,他有两个参数m,n,那么args就传入(m, n)即可 
kwargs表示调用对象的字典 
name是别名,相当于给这个进程取一个名字 
group分组,实际上不使用 

另外,创建一个多进程需要导入multiprocessing 模块,并加入一个if 判断 即:if __name__ == "__main__" :
    function(创建多进程的语句)


先用一个实例来感受一下:
import multiprocessing

def process(num):
    print 'Process:', num               #定义一个函数,

if __name__ == '__main__':
    for i in range(5):                            #启动五个进程
        p = multiprocessing.Process(target=process, args=(i,))             #生成多进程
        p.start()                  启动多进程
最简单的创建Process的过程如上所示,target传入函数名,args是函数的参数,是元组的形式,如果只有一个参数,那就是长度为1的元组,然后调用start()方法即可启动多个进程了;另外还可以通过 cpu_count() 方法,还有 active_children() 方法获取当前机器的 CPU 核心数量(CPU主要的工作就是处理和运算数据,所以,CPU运算速度、主频、缓存、核心数,这几个参数就决定了CPU的好坏,CPU的主频越高、缓存越大、核心数越多,这样的CPU运转速度就很快,处理图形图像文件起来,速度就越快)以及得到目前所有的运行的进程。通过一个实例来感受一下:
import multiprocessing
import time
def process(num):
    time.sleep(num)              #sleep() 方法暂停给定秒数(可以是浮点数)后执行程序。该函数没有返回值
    print 'Process:', num              

if __name__ == '__main__':
    for i in range(5):
        p = multiprocessing.Process(target=process, args=(i,))
        p.start()

    print('CPU number:' + str(multiprocessing.cpu_count()))           #cpu_count() :获取当前机器的 CPU 核心数量
    for p in multiprocessing.active_children():                                # active_children() :得到目前所有的运行的进程
        print('Child process name: ' + p.name + ' id: ' + str(p.pid))

    print('Process Ended')
运行结果:
Process: 0
CPU number:8
Child process name: Process-2 id: 9641
Child process name: Process-4 id: 9643
Child process name: Process-5 id: 9644
Child process name: Process-3 id: 9642
Process Ended
Process: 1
Process: 2
Process: 3
Process: 4
》》》自定义类:
另外你还可以继承Process类,自定义进程类,实现run方法即可,用一个实例来感受一下:
from multiprocessing import Process
import time
class MyProcess(Process):
    def __init__(self, loop):
        Process.__init__(self)
        self.loop = loop

    def run(self):
        for count in range(self.loop):
            time.sleep(1)
            print('Pid: ' + str(self.pid) + ' LoopCount: ' + str(count))

if __name__ == '__main__':
    for i in range(2, 5):
        p = MyProcess(i)
        p.start()

(2)Queue:
进程间的通信队列需要用 multiprocessing.Queue:
Queue.empty() 如果队列为空,返回True, 反之False
Queue.full() 如果队列满了,返回True,反之False
Queue.get([block[, timeout]]) 获取队列,timeout等待时间
Queue.get_nowait() 相当Queue.get(False)
Queue.put(item) 阻塞式写入队列,timeout等待时间
Queue.put_nowait(item) 相当Queue.put(item, False)


(3)Pool(如果要启动大量的子进程,可以用进程池的方式批量创建子进程):
》》》产生背景(转载自百度):
在利用Python进行系统管理的时候,特别是同时操作多个文件目录,或者远程控制多台主机,并行操作可以节约大量的时间。当被操作对象数目不大时,可以直接利用multiprocessing中的Process动态成生多个进程,十几个还好,但如果是上百个,上千个目标,手动的去限制进程数量却又太过繁琐,此时可以发挥进程池的功效。 Pool可以提供指定数量的进程,供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来它。

Pool的用法有阻塞和非阻塞两种方式:
阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态。阻塞即要等到回调结果出来,在有结果之前,当前进程会被挂起;非阻塞即为添加进程后,不一定非要等到改进程执行完就添加其他进程运行。现用一个实例感受一下非阻塞的用法:
from multiprocessing import Lock, Pool
import time


def function(index):
    print 'Start process: ', index
    time.sleep(3)
    print 'End process', index


if __name__ == '__main__':
    pool = Pool(processes=3)
    for i in xrange(4):
        pool.apply_async(function, (i,))

    print "Started processes"
    pool.close()                                   #关闭pool,使其不再接受新的任务。
    pool.join()                                     #主进程阻塞等待子进程的退出, join方法要在close或terminate(结束工作进程,不再处理未处理的任务)之后使用。
    print "Subprocess done."
在这里利用了apply_async方法,即非阻塞。
运行结果:
Started processes
Start process: Start process:  0
1
Start process:  2
End processEnd process 0
1
Start process:  3
End process 2
End process 3
Subprocess done.

可以发现在这里添加三个进程进去后,立马就开始执行,不用非要等到某个进程结束后再添加新的进程进去。
下面再看看阻塞的用法:
from multiprocessing import Lock, Pool
import time


def function(index):
    print 'Start process: ', index
    time.sleep(3)
    print 'End process', index


if __name__ == '__main__':
    pool = Pool(processes=3)
    for i in xrange(4):
        pool.apply(function, (i,))

    print "Started processes"
    pool.close()
    pool.join()
    print "Subprocess done."
在这里只需要把apply_async改成apply即可。
运行结果如下:

Start process:  0
End process 0
Start process:  1
End process 1
Start process:  2
End process 2
Start process:  3
End process 3
Started processes
Subprocess done.


下面再次对函数进行解释:
apply_async(func[, args[, kwds[, callback]]]) 它是非阻塞,apply(func[, args[, kwds]])是阻塞的。
close() 关闭pool,使其不在接受新的任务。
terminate() 结束工作进程,不在处理未完成的任务。
join() 主进程阻塞,等待子进程的退出, join方法要在close或terminate之后使用。

当然每个进程可以在各自的方法返回一个结果。apply或apply_async方法可以拿到这个结果并进一步进行处理。
from multiprocessing import Lock, Pool
import time


def function(index):
    print 'Start process: ', index
    time.sleep(3)
    print 'End process', index
    return index

if __name__ == '__main__':
    pool = Pool(processes=3)
    for i in xrange(4):
        result = pool.apply_async(function, (i,))
        print result.get()
    print "Started processes"
    pool.close()
    pool.join()
    print "Subprocess done."
运行结果:

Start process:  0
End process 0
0
Start process:  1
End process 1
1
Start process:  2
End process 2
2
Start process:  3
End process 3
3
Started processes
Subprocess done.
      另外还有一个非常好用的map方:pool.map(func, iterable)。用map()函数进行进程运行,func参数为需运行的函数,在爬虫实战中,为爬虫函数。iterable为迭代参数,在爬虫实战中,可为多个URL列表进行迭代。    
      如果现在有一堆数据要处理,每一项都需要经过一个方法来处理,那么map非常适合。比如现在有一个数组,包含了所有的URL,而现在已经有了一个方法用来抓取每个URL内容并解析,那么可以直接在map的第一个参数传入方法名,第二个参数传入URL数组。现在我们用一个实例来感受一下:
from multiprocessing import Pool
import requests
from requests.exceptions import ConnectionError


def scrape(url):
    try:
        print requests.get(url)
    except ConnectionError:
        print 'Error Occured ', url
    finally:
        print 'URL ', url, ' Scraped'


if __name__ == '__main__':
    pool = Pool(processes=3)
    urls = [
        'https://www.baidu.com',
        'http://www.meituan.com/',
        'http://blog.csdn.net/',
        'http://xxxyxxx.net'
    ]
    pool.map(scrape, urls)
在这里初始化一个Pool,指定进程数为3,如果不指定,那么会自动根据CPU内核来分配进程数。然后有一个链接列表,map函数可以遍历每个URL,然后对其分别执行scrape方法。

运行结果:

<Response [403]>
URL  http://blog.csdn.net/  Scraped
<Response [200]>
URL  https://www.baidu.com  Scraped
Error Occured  http://xxxyxxx.net
URL  http://xxxyxxx.net  Scraped
<Response [200]>
URL  http://www.meituan.com/  Scraped
可以看到遍历就实现了。

(3)多线程学习(线程是在同一时间需要完成多项任务的时候实现的):
在上面,我还是知道了多任务可以由多进程完成,也可以由一个进程内的多线程完成;进程是由若干线程组成的,一个进程至少有一个线程。
Python的标准库提供了两个模块:thread和threading,thread是低级模块,threading是高级模块,对thread进行了封装。绝大多数情况下,我们只需要使用threading这个高级模块

查看线程数:使用threading.enumerate()函数便可以看到当前线程的数量。
查看当前线程的名字:
使用threading.current_thread()可以看到当前线程的信息。

启动一个线程就是把一个函数传入并创建Thread实例,然后调用start()开始执行:
import time, threading            # 新线程执行的代码:
def loop():
    print 'thread %s is running...' % threading.current_thread().name
    n = 0
    while n < 5:
        n = n + 1
        print 'thread %s >>> %s' % (threading.current_thread().name, n)
        time.sleep(1)
    print 'thread %s ended.' % threading.current_thread().name

print 'thread %s is running...' % threading.current_thread().name
t = threading.Thread(target=loop, name='LoopThread')
t.start()
t.join()
print 'thread %s ended.' % threading.current_thread().name
执行结果如下:
thread MainThread is running...
thread LoopThread is running...
thread LoopThread >>> 1
thread LoopThread >>> 2
thread LoopThread >>> 3
thread LoopThread >>> 4
thread LoopThread >>> 5
thread LoopThread ended.
thread MainThread ended.

由于任何进程默认就会启动一个线程,我们把该线程称为主线程,主线程又可以启动新的线程,Python的threading模块有个current_thread()函数,永远返回当前线程的实例。主线程实例的名字叫MainThread,子线程的名字在创建时指定,我们用LoopThread命名子线程。名字仅仅在打印时用来显示,完全没有其他意义,如果不起名字Python就自动给线程命名为Thread-1,Thread-2……


锁机制:(先放放吧!不研究这个多线程了,如果再次遇到就补充
     多线程共享全局变量的问题:多线程都是在同一个进程中运行的,因此在进程中的全局变量所有线程都是可共享的。这就造成了一个问题,因为线程执行的顺序是无序的,有可能会造成数据错误。     为了解决以上使用共享全局变量的问题。threading提供了一个Lock类,这个类可以在某个线程访问某个变量的时候加锁,其他线程此时就不能进来,直到当前线程处理完后,把锁释放了,其他线程才能进来处理。

(三)time模块:
1.time模块中时间表现的格式主要有三种:
>>>timestamp时间戳,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。函数time.time()用于获取当前时间戳, 如下实例:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import time;                              # 引入time模块
ticks = time.time()
print "当前时间戳为:", ticks
以上实例输出结果:
当前时间戳为: 1459994552.51


>>>struct_time时间元组,共有九个元素组。
时间元组:

属性字段
tm_year4位数年2019
tm_mon1 到 12
tm_mday1 到 31
tm_hour小时0到23
tm_min分钟0到59
tm_sec0到61 (60或61 是闰秒)
tm_wday一周的第几日0到6 (0是周一)
tm_yday一年的第几日1到366 (儒略历)
tm_isdst夏令时  -1, 0, 1, -1是决定是否为夏令时的旗帜

例:
———获取当前时间:
从返回浮点数的时间戳方式向时间元组转换,只要将浮点数传递给如localtime之类的函数。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import time
localtime = time.localtime(time.time())
print "本地时间为 :", localtime
以上实例输出结果:
本地时间为 : time.struct_time(tm_year=2016, tm_mon=4, tm_mday=7, tm_hour=10, tm_min=3, tm_sec=27, tm_wday=3, tm_yday=98, tm_isdst=0)

———获取格式化的时间:
你可以根据需求选取各种格式,但是最简单的获取可读的时间模式的函数是asctime():
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import time
localtime = time.asctime( time.localtime(time.time()) )
print "本地时间为 :", localtime
以上实例输出结果:
本地时间为 : Thu Apr  7 10:05:21 2016

————格式化日期
我们可以使用 time 模块的 strftime 方法来格式化日期,:time.strftime(format[, t])
实例演示:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import time       
print time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())                 # 格式化成2016-03-20 11:45:39形式
print time.strftime("%a %b %d %H:%M:%S %Y", time.localtime())             # 格式化成Sat Mar 28 22:24:24 2016形式
a = "Sat Mar 28 22:24:24 2016"
print time.mktime(time.strptime(a,"%a %b %d %H:%M:%S %Y"))             # 将格式字符串转换为时间戳
以上实例输出结果:
2016-04-07 10:25:09
Thu Apr 07 10:25:09 2016
1459175064.0


>>>format time 格式化时间,已格式化的结构使时间更具可读性。包括自定义格式和固定格式。

python中时间日期格式化符号: 
%y两位数的年份表示(00-99)
%Y四位数的年份表示(000-9999)
%m月份(01-12)
%d月内中的一天(0-31)
%H24小时制小时数(0-23)
%I 12小时制小时数(01-12)
%M分钟数(00=59)
%S秒(00-59)
%a本地简化星期名称
%A本地完整星期名称
%b本地简化的月份名称
%B本地完整的月份名称
%c本地相应的日期表示和时间表示
%j年内的一天(001-366)
%p本地A.M.或P.M.的等价符
%U一年中的星期数(00-53)星期天为星期的开始
%w星期(0-6),星期天为星期的开始
%W一年中的星期数(00-53)星期一为星期的开始
%x本地相应的日期表示
%X本地相应的时间表示
%Z当前时区的名称
%%%号本身


2.Time 模块包含了以下内置函数,既有时间处理的,也有转换时间格式的:
可能不一定在爬虫中使用,但是转载一下,等需要的时候再看)time.altzone
返回格林威治西部的夏令时地区的偏移秒数。如果该地区在格林威治东部会返回负值(如西欧,包括英国)。对夏令时启用地区才能使用。
time.asctime([tupletime])
接受时间元组并返回一个可读的形式为"Tue Dec 11 18:07:14 2008"(2008年12月11日 周二18时07分14秒)的24个字符的字符串。
time.clock( )
用以浮点数计算的秒数返回当前的CPU时间。用来衡量不同程序的耗时,比time.time()更有用。
time.ctime([secs])
作用相当于asctime(localtime(secs)),未给参数相当于asctime()
time.gmtime([secs])
接收时间戳(1970纪元后经过的浮点秒数)并返回格林威治天文时间下的时间元组t。注:t.tm_isdst始终为0
time.localtime([secs])
接收时间戳(1970纪元后经过的浮点秒数)并返回当地时间下的时间元组t(t.tm_isdst可取0或1,取决于当地当时是不是夏令时)。
time.mktime(tupletime)
接受时间元组并返回时间戳(1970纪元后经过的浮点秒数)。
time.sleep(secs)
推迟调用线程的运行,secs指秒数。
time.strftime(fmt[,tupletime])
接收以时间元组,并返回以可读字符串表示的当地时间,格式由fmt决定。
time.strptime(str,fmt='%a %b %d %H:%M:%S %Y')
根据fmt的格式把一个时间字符串解析为时间元组。
time.time( )
返回当前时间的时间戳(1970纪元后经过的浮点秒数)。
time.tzset()
根据环境变量TZ重新初始化时间相关设置。


(四)datetime模块:
1.在datetime模块中,提供了如下四个常用的类:
date:属性:year, month和day 。
time:属性:hour, minute, second, microsecond和tzinfo。
datetime:日期和时间的组合。 属性:year ,month, day, hour, minute,second,microsecond和tzinfo 。
timedelta:表示两个date, time或datetime的时间差。

2.timedelta :   
datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0) 
以上所有的参数都是可选的,默认为零,参数可以是整数、浮点数、 正数、负数。
3.date:
datetime.date(year, month, day)所有的参数都是必需的,参数可以是整数。
4.time:
datetime.time(hour=0, minute=0, second=0, microsecond=0, tzinfo=None)
所有的参数都是可选。
5.datetime:
datetime.datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None)
必须的参数是 year(年)、month(月)、day(日);

(五)python中的json模块:
     (官方解释不懂,先把定义摆出来吧)json 是一种轻量级的数据交换格式。Python使用 json 模块来对 JSON 数据进行编解码,它主要提供了四个方法: dumps、dump、loads、load。
1.dump和dumps:dump和dumps对python对象进行序列化。将一个Python对象进行JSON格式的编码。

(1)dump函数:json.dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)
其中:
obj:                    表示是要序列化的对象。
fp:                      文件描述符,将序列化的str保存到文件中。json模块总是生成str对象,而不是字节对象;因此,fp.write()必须支持str输入。
skipkeys:             默认为False,如果skipkeys为True,(默认值:False),则将跳过不是基本类型(str,int,float,bool,None)的dict键,不会引发TypeError。
ensure_ascii:        默认值为True,能将所有传入的非ASCII字符转义输出。如果ensure_ascii为False,则这些字符将按原样输出。
check_circular:     默认值为True,如果check_circular为False,则将跳过对容器类型的循环引用检查,循环引用将导致OverflowError。
allow_nan:           默认值为True,如果allow_nan为False,则严格遵守JSON规范,序列化超出范围的浮点值(nan,inf,-inf)会引发ValueError。
indent:                设置缩进格式,默认值为None,选择的是最紧凑的表示。如果indent是非负整数或字符串,那么JSON数组元素和对象成员将使用该缩进级别进行输入;indent为0,负数或“”仅插入换行符;indent使用正整数缩进多个空格;如果indent是一个字符串(例如“\t”),则该字符串用于缩进每个级别。
separators:            去除分隔符后面的空格,默认值为None,如果指定,则分隔符应为(item_separator,key_separator)元组。如果缩进为None,则默认为(’,’,’:’);要获得最紧凑的JSON表示,可以指定(’,’,’:’)以消除空格。
default:                  默认值为None,如果指定,则default应该是为无法以其他方式序列化的对象调用的函数。它应返回对象的JSON可编码版本或引发TypeError。如果未指定,则引发TypeError。
sort_keys:               默认值为False,如果sort_keys为True,则字典的输出将按键值排序。

(2)dumps函数:json.dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)
dumps函数不需要传文件描述符,其他的参数和dump函数的一样。
(3)实例:import json
# dumps可以格式化所有的基本数据类型(列表,数字,字符串,字典)为字符串
data1 = json.dumps([])                                              # 列表
print(data1, type(data1))
data2 = json.dumps(2)                                              # 数字
print(data2, type(data2))
data3 = json.dumps('3')                                            # 字符串
print(data3, type(data3))
dict = {"name": "Tom", "age": 23}                             # 字典
data4 = json.dumps(dict)
print(data4, type(data4))
with open("test.json", "w", encoding='utf-8') as f:          #这几行代码有点糊涂了
    f.write(json.dumps(dict, indent=4))                      # indent 超级好用,格式化保存字典,默认为None,小于0为零个空格
    json.dump(dict, f, indent=4)                                # 传入文件描述符,和dumps一样的结果

得到的输出结果如下:格式化所有的数据类型为str类型
[] <class 'str'>
2 <class 'str'>
"3" <class 'str'>
{"name": "Tom", "age": 23} <class 'str'>

test.json中的内容:
{
    "name": "Tom",
    "age": 23
}

2.load和loads:load和loads反序列化方法,将json格式数据解码为python对象

(1)load函数:
json.load(fp, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw
其中:
fp: 文件描述符,将fp(.read()支持包含JSON文档的文本文件或二进制文件)反序列化为Python对象。
object_hook: 默认值为None,object_hook是一个可选函数,此功能可用于实现自定义解码器。指定一个函数,该函数负责把反序列化后的基本类型对象转换成自定义类型的对象。
parse_float: 默认值为None,如果指定了parse_float,用来对JSON float字符串进行解码,这可用于为JSON浮点数使用另一种数据类型或解析器。
parse_int: 默认值为None,如果指定了parse_int,用来对JSON int字符串进行解码,这可以用于为JSON整数使用另一种数据类型或解析器。
parse_constant:默认值为None,如果指定了parse_constant,对-Infinity,Infinity,NaN字符串进行调用。如果遇到了无效的JSON符号,会引发异常。

如果进行反序列化(解码)的数据不是一个有效的JSON文档,将会引发 JSONDecodeError异常。

(2)loads函数:
json.loads(s, *, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
其中:
s: 将s(包含JSON文档的str,bytes或bytearray实例)反序列化为Python对象。 
encoding: 指定一个编码的格式。 
loads也不需要文件描述符,其他参数的含义和load函数的一致。

(3)实例:
import json
dict = '{"name": "Tom", "age": 23}'   # 将字符串还原为dict
data1 = json.loads(dict)
print(data1, type(data1))
with open("test.json", "r", encoding='utf-8') as f:      看不懂了!
    data2 = json.loads(f.read())                     # load的传入参数为字符串类型
    print(data2, type(data2))
    f.seek(0)                                               # 将文件游标移动到文件开头位置
    data3 = json.load(f)
    print(data3, type(data3))
运行结果如下:
{'name': 'Tom', 'age': 23} <class 'dict'>
{'name': 'Tom', 'age': 23} <class 'dict'>
{'name': 'Tom', 'age': 23} <class 'dict'>

(六)os模块:1.常用函数:

(1)os.getcwd()函数:功能——获取当前目录,python 的工作目
例:
import os
pwd = os.getcwd()
print (pwd)

(2)os.name 函数:功能——获取当前使用的操作系统(其中 'nt' 是 windows,'posix' 是 linux 或者 unix)
import os
name = os.name
if name == 'posix':                          
    print ("this is Linux or Unix")
elif name == 'nt':
    print ("this is windows")
else:
    print ("this is other system")

(3)os.remove()函数:功能——删除指定文件

例:删除 file.txt 文件
import os
os.remove(’file.txt‘)


(4)os.removedirs()函数:功能——删除指定目录
例:删除 file目录:
import os
os.removedirs(‘file’)


(5)os.system()函数: 功能——运行shell命令   (shell命令应该不做了解吧!)                
例:执行ls -a > 1.txt命令
import os  
os.system(‘ls -a > 1.txt’)

(6)os.mkdir()函数:功能——创建一个新目录
例:创建一个 file 目录
import os            
os.mkdir(‘file’)


(7)os.chdir()函数:功能——改变当前路径到指定路径
例:我现在从当前路径到 filepath 所指定的路径下
import os
filepath = '/home'
pwd = os.getcwd()
print (pwd) 
os.chdir(filepath)
pwd = os.getcwd()
print (pwd)

(8)os.listdir()函数:功能——返回指定目录下的所有目录和文件
例:列出当前目录下的所有文件和目录
import os
pwd = os.getcwd()
name = os.listdir(pwd)
for filename in name:
    print (filename)

(七)xlwt模块:

1.作用:python爬取到的数据需要存储,Excel是个不错的选择,第三方库xlwt支持python语言对Excel表格的操作.
2.使用代码:(转载例子)
import xlwt                                          # 导入xlst模块
wb = xlwt.Workbook()                          # 创建 Workbook
ws = wb.add_sheet('test_sheet')            #创建 worksheet
ws.write(0, 0, '球队')                             #写入第一行内容 ws.write(a, b, c)  a:行,b:列,c:内容
ws.write(0, 1, '号码')
ws.write(0, 2, '姓名')
ws.write(0, 3, '位置')
wb.save('./myExcel.xls')                          # 保存文件



效果如图:

 
再写入一些数据:

data = [
        {
                'Team': '湖人',
                'Number': '34',
                'Name': '奥尼尔',
                'Positions': '中锋'
        },
        {
                'Team': '湖人',
                'Number': '24',
                'Name': '科比',
                'Positions': '后卫'
        },
        {
                'Team': '湖人',
                'Number': '23',
                'Name': '詹姆斯',
                'Positions': '前锋'
        }
]

for i, item in enumerate(data):
        ws.write(i+1, 0, item['Team'])
        ws.write(i+1, 1, item['Number'])
        ws.write(i+1, 2, item['Name'])
        ws.write(i+1, 3, item['Positions'])


 

3.补充知识:

(1)write_merge方法:
write_merge(x, x + m, y, w + n, string, sytle)
x表示行,y表示列,m表示跨行个数,n表示跨列个数,string表示要写入的单元格内容,style表示单元格样式。其中,x,y,w,h,都是以0开始计算的。

 


http://www.ppmy.cn/news/706805.html

相关文章

HTTPGet 与HTTPPost的区别

HTTPGet 与HTTPPost的区别 今天在老师工作室做项目的时候&#xff0c;突然看到一个页面用了2种不同的传值类型&#xff0c;突然有了兴趣&#xff0c;想弄明白本质的区别&#xff0c;虽然以前用的知道2种的用法&#xff0c;但是还是云里雾里的&#xff0c;下面是那位大神的文章&…

学习伟大的Python的第六天

1.post请求 get请求与post请求的区别 从网上找到很好的解释&#xff1a; 一.在我大万维网世界中&#xff0c;TCP就像汽车&#xff0c;我们用TCP来运输数据&#xff0c;它很可靠&#xff0c;从来不会发生丢件少件的现象。但是如果路上跑的全是看起来一模一样的汽车&#xff0c;那…

python学习笔记及作业(post请求,request的高级用法,selenium)

1.post请求 get请求与post请求的区别 从网上找到很好的解释&#xff1a; 一.在我大万维网世界中&#xff0c;TCP就像汽车&#xff0c;我们用TCP来运输数据&#xff0c;它很可靠&#xff0c;从来不会发生丢件少件的现象。但是如果路上跑的全是看起来一模一样的汽车&#xff0c;那…

DS博客作业03--栈和队列

目录 1.本周学习总结2.PTA实验作业2.1 题目1&#xff1a;jmu-报数游戏 2.1.1设计思路2.1.2代码截图2.1.3本题PTA提交列表说明2.2 题目2&#xff1a;银行排队问题之单队列多窗口服务 2.2.1设计思路2.2.2代码截图2.2.3本题PTA提交列表说明2.3 题目3&#xff1a;符号配对 2.3.1设计…

2020秋招 C++软件开发/游戏开发 面试知识整理汇总

鄙人的2020秋招目前已经基本结束&#xff0c;最终拿了六家公司的offer&#xff0c;在综合比较之后目前已经有了明确的偏向&#xff0c;那就是去某公司转行Java&#xff0c;至于原因有很多层&#xff0c;我即使在做了这个决定半年后还是不敢肯定这个决定是否真的正确&#xff0c…

一些界面标准规范

一些界面标准规范 一&#xff1a;遵循一致的准则&#xff0c;确立标准并遵循 无论是控件使用&#xff0c;提示信息措辞&#xff0c;还是颜色、窗口布局风格&#xff0c;遵循统一的标准&#xff0c;做到真正的一致。 这样得到的好处&#xff1a; 1&#xff1a;使用户使用起来能够…

海淀驾校拿本过程

开始 大学的时候就想着考驾照&#xff0c;但是由于时间原因金钱原因&#xff0c;没有考。因此选择了工作之后再考。从今年&#xff08;2017&#xff09;4月2日到7月18日&#xff0c;历时107天&#xff08;3个多月&#xff09;&#xff0c;成功拿到了驾照。本文主要是对我整个考…

[ZZ]一些界面标准规范(来自因特网)

一些界面标准规范&#xff08;来自因特网) [理论] 通用界面指南 -------------------------------------------------------------------------------- □ 作者:Bruce 2003-1-7 11:00:07 一&#xff1a;遵循一致的准则&#xff0c;确立标准并遵循 无论是控件使用&#x…