前一段时间写了不少Python的爬虫程序, 为此还看了极客学院上的一些教程, 现在来简单总结一下. 主要介绍用requests + lxml的方式, scrapy的话之前写过一篇介绍性的文章, 这里就不重复了. 而且感觉一般简单的爬虫项目, 一个Python文件就基本可以搞定, 没必要用scrapy建立一个工程文件夹搞那么正式...

安装需要的库(python2):

pip install requests, lxml

然后在Python程序最开始导入:

import requests  
from lxml import etree

requests基础用法

抓取html内容

用requests获取目标网址的html代码非常简单, 只需要用requests.get方法, 传入网址URL即可.

举个例子, 想要抓取维基语录的HTML内容, 代码很简单:

url = 'https://zh.wikiquote.org/zh-cn/阿爾伯特·愛因斯坦'  
r ...

总结一下用python撸codejam时常用的一些库, 并且给一些简单的例子. 发现用python撸codejam非常合适: codejam的时间要求不严格(4/8分钟), 而且程序只要本地运行. 正好可以使用python简洁的语法和丰富的函数库.

collections

py自带的一些好用的数据结构...
https://docs.python.org/2/library/collections.html

from collections import Counter, deque, defaultdict

itertools

主要是用来穷举的时候它里面一些函数很好用...

https://docs.python.org/2/library/itertools.html

>>> from itertools import product, combinations   
>>> a = 'ABCD'; b='EFG'   
>>> for p in product(a,b):    
print ...

http://www.imooc.com/learn/317

模块和包

: 文件夹 (可以有多级), 且包含__init__.py文件(每层都要有) 模块: py文件

代码分开放在多个py文件(模块名=文件名). 同名变量互不影响.

模块名冲突: 把同名模块放在不同中.

导入模块

from math import log
from logging import log as logger

引用时: 使用完整的路径(包+模块名). ex. p1.util.f()

动态导入模块

try:
    from cStringIO import ...

http://www.imooc.com/learn/317

函数式编程: 更抽象, 更脱离指令(计算机), 更贴近计算(数学).

  • 不需要变量 (python允许有变量, 所以python非纯函数式)
  • 高阶函数
  • 闭包: 返回函数
  • 匿名函数

高阶函数

  • 变量可以指向函数 f=abs; f(-10)
  • 函数名: 就是指向函数的变量 abs=len
  • 高阶函数: 接收函数作为参数的函数

    def add(x,y,f):
    return f(x)+f(y)
    add(-5, 9, abs)

map()

map()是 Python 内置的高阶函数 ...

python科学计算包的基础是numpy, 里面的array类型经常遇到. 一开始可能把这个array和python内建的列表(list)混淆, 这里简单总结一下列表(list), 多维数组(np.ndarray)和矩阵(np.matrix)的区别.

list列表

列表属于python的三种基本集合类型之一, 其他两种是元组(tuple)和字典(dict). tuple和list区别主要在于是不是mutable的.

list和java里的数组不同之处在于, python的list可以包含任意类型的对象, 一个list里可以包含int, string或者其他任何对象, 另外list是可变长度的(list有append, extendpop等方法).

所以, python内建的所谓"列表"其实是功能很强大的数组, 类比一下可以说它对应于java里面的ArrayList<Object> .

ndarray多维数组

ndarray是numpy的基石, 其实它更像一个java里面的标准数组: 所有元素有一个相同数据类型(dtype), 不过大小不是固定的.

ndarray对于大计算量的性能非常好, 所以list要做运算的时候一定要先转为array(np.array(_a_list_ ...

Scrapy是用来爬取数据的很流行的包, 这里小记一下. 以前几天做的一个爬虫为例子, 这个爬虫把韩寒一个app的前九百多期的文章抓了下来.

I. installation

scrapy的安装参考: http://scrapy-chs.readthedocs.org/zh_CN/latest/topics/ubuntu.html

(直接pip安装的好像缺少什么包)

II. prerequisite

XPath

需要学习scrapy首先需要会XPath, 这是一种方便与在html/xml文档里查找所需元素的语句. 这个还是很好学的, 其实只需要花一刻钟时间看看w3school的教程, 就可以掌握够用的知识进行下一步了.

这里总结一下我觉得会用到的语句(不全, 不过经常用到):

  • //book 选取所有名字叫做book的元素
  • bookstore/book 选取bookstore的子元素中所有叫book的元素
  • //title[@lang='eng'] 选取lang属性为"eng"的所有title元素
  • //titile/text() 选取title元素的文字内容
  • descendant-or-self::text(): 选取自己或者所有后代节点的文字内容

另外还有个在线测试XPath语句的网站 ...

在处理大量数的时候, 如果输出类似 "process i out of n files..." 这样的内容来指示进度的话, 虽然可以显示目前的进度(用来安慰等待的心情...)但有个问题是, 如果输出了太多行(比如一万行...), 就看不到前面的内容了...

所以想找一个命令行下面的进度条, 其实python已经有了(不止一个)进度条的包了, 比如progressbar, 但是不知为什么这个包在windows下面没有能做到刷新显示 -- 就是刷新进度的时候, 没有把原先那一行去掉, 而是在下面再输出了一行... (不过后来在linux下面使用这个包是没问题的, 好奇怪...)

所以想办法自己写了一个, 发现要实现一个简单的进度条还是很简单的, 关键就是使用\r, 这样会把光标移动到当前行的开头: 这样下次输出的时候就会把原先的内容冲掉了.

代码只有不到二十行:

import sys

class SimpleProgressBar():
    def __init__(self, width=50):
        self.last_x = -1
        self.width = width

    def ...

Learning IPython for Interactive Computing and Data Visualization这本书的前两章的笔记, 这本书还被放在了IPython官网上, 虽然只有一百页多一点点, 但是讲的内容却很丰富, 介绍了IPython, numpy, pandas以及并行计算等方面.

(在开始系统学IPython之前简单使用过IPython, 那时候我还是更喜欢bpython的代码提示功能...)

ch1: 10 IPython essentials

  • 在任何变量后面加问号?或者双问号??, 将会输出详细的信息(按q退出), ??的信息更加详细些
  • Tab Completion: 没啥好说的 没有bpython做的好 也凑合吧...
  • _, __, ___保存最近三次的输出; _i, __i, ___i保存最近三次的输入(作为字符串保存)

magic commands

  • 在IPython里面可以使用一些标准unix命令, 比如cd, pwd,ls等 ...

首先, 导入pandas import pandas as pd

以及开启pylab: IPython里输入%pylab

http://www.bearrelroll.com/2013/05/python-pandas-tutorial/

基本操作

http://cloga.info/python/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6/2013/09/17/pandas_intro/

pandas和numpy的关系: pandas是建立在numpy上面的, pandas可以处理不同类型的数据集合(heterogeneous data set: DataFrame), numpy处理的是相同类型的数据集合(homogeneous data set: ndarray)

读写csv文件 ...

python的pickle/unpickle机制可以非常方便的保存一些计算的中间结果, 这一点java虽然也可以做到, 但是java里面的包的名字实在是长的让人记不住...

不过今天在使用pickle的时候遇到了一个很奇怪的问题.

是这样的, 原本写了一个程序main.py, 这个程序里进行了一些计算并且pickle下了这些内容, 后来我觉得一个程序main.py写这么多实在太长了, 于是就把那些辅助函数以及class的定义通通放进了一个util.py文件里. 并且在main.py的第一行写上:

from util import *

按理说这应该没有问题, 和一个main文件时运行的效果相同的, 但是当我运行的时候却显示util.py里面这行unpickle的语句有错误:

    airport_info = pk.load(file('airport_info.dict', 'rb')) 
    >>AttributeError: 'module' object has no attribute 'Airport'

其中Airport是我定义的一个类, 本来在main.py里面, 后来被我移动到了util.py里面...

感觉很奇怪, 于是去水源求助 ...