git 基本操作

记录一下主要过程。

1.先在github上创建一个Responsibility,例如取名Myfirst,接着在本地bash里选一个文件夹,并cd到该文件夹
mkdir Myfirst   # 新建一个文件夹
git init   # 初始化本地仓库

2.然后把要上传的东西复制进去,比如有

baidu_parser.py
data.txt

git add baidu_parser.py
git add data.txt
git commit -m “upload 2 files”

3. 提交远程仓库
git remote add origin git@github.com:fancoo/Myfirst.git      # 连接
git push -u origin master     # push

4. 如果远程修改了,要使本地同步:
git fetch
git merge

Advertisements

Linux下使用服务器运行程序的基本命令

之前运行一个爬虫程序,数据有点大估计得爬好几天,于是简单学习了几句Linux上有关操作。

# 这个命令和win上类似,调到data目录下
cd /data
# 输入rz,会弹出一个窗口让你选取文件
# 从而将本地文件上传到服务器
rz 
# 将服务器上的文件拿下来
sz sample.txt
# 删除文件
rm sample.txt
# 递归删除含有文件的目录
rm -rf 目录名(文件夹名)
# 运行py程序
python test.py
# 列出本文件夹下所有文件
ll
# 让服务器后台运行(关闭本机程序也可继续运行)
nohup python test.py &

Python常用内置函数

经常使用Python的一些函数,但每次都查过之后第二次用又记不住它们的特性,现对它们做一个总结。

1. strip(rm)
用于移除字符串头尾指定的字符(默认为空格)。当rm为空时,默认删除空白符(包括’\n’, ‘\r’,  ‘\t’,  ‘ ‘)

>>> a = ' 123'
>>> a.strip()
'123'
>>> a = '\t\sABBA'
>>> a.strip()
'\\sABBA'
>>> a.strip('2')
'\t\\sABBA'

 

2. split(rm)
通过指定分隔符对字符串进行切片,当rm为空时,默认以空白符切片(包括’\n’, ‘\r’,  ‘\t’,  ‘ ‘)

>>> a = '1 2 3 4 5'
>>> a.split()
['1', '2', '3', '4', '5']
>>> a = '1+2+3+4+5+6'
>>> a.split('+')
['1', '2', '3', '4', '5', '6']

 

3. map(function, sequence[, sequence, …])
对sequence中的item依次执行function(item),执行结果输出为list

>>> map(str, range(5))
['0', '1', '2', '3', '4']

 

4. reduce(function, sequence[, initial]) 
对sequence中的item顺序迭代调用function,函数必须要有2个参数。要是有第3个参数,则表示初始值,可以继续调用初始值,返回一个值。

>>> def add(x, y):return x+y

>>> reduce(add, range(10))
45
>>> reduce(lambda x,y:x*y, range(1, 6), 3)  # 注意range(a, b)包含a不包含b
360

 

5. filter(function or None, sequence)
对sequence中的item依次执行function(item),将执行结果为True(!=0)的item组成一个List/String/Tuple(取决于sequence的类型)返回,False则退出(0),进行过滤。

>>> def div(n):return n%2

>>> filter(div, range(10))
[1, 3, 5, 7, 9]

6. set()
set是一个无序不重复元素集, 基本功能包括关系测试和消除重复元素. 集合对象还支持union(联合), intersection(交), difference(差)和sysmmetric difference(对称差集)等数学运算.
sets 支持 x in set, len(set),和 for x in set。作为一个无序的集合,sets不记录元素位置或者插入点。因此,sets不支持 indexing, slicing, 或其它类序列(sequence-like)的操作。

下面来点简单的小例子说明把。

>>> x = set('spam')
>>> y = set(['h','a','m'])
>>> x, y
(set(['a', 'p', 's', 'm']), set(['a', 'h', 'm']))
>>> x & y  # 交集
set(['a', 'm'])  

>>> x | y  # 并集
set(['a', 'p', 's', 'h', 'm'])  

>>> x - y  # 差集
set(['p', 's'])

集合支持一系列标准操作,包括并集、交集、差集和对称差集,例如:

a = t | s          # t 和 s的并集  

b = t & s          # t 和 s的交集  

c = t – s          # 求差集(项在t中,但不在s中)  

d = t ^ s          # 对称差集(项在t或s中,但不会同时出现在二者中)

7. enumerate(list)
enumerate会将数组或列表组成一个索引序列。使我们在获取索引和索引内容的时候更加方便。

>>> mlist = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> for index, text in enumerate(mlist):
print index, text

0 a
1 b
2 c
3 d
4 e
5 f
6 g

四.利用sklearn训练分类器并预测

在(三)中,我们已经得到了训练样本(包含已经标记了正负的)的libsvm矩阵格式数据,同理我们也可以得到测试样本集的矩阵数据,在本文中,我们将使用sklearn中的svm库对样本进行训练,然后保存模型,并对测试数据进行预测,得到准确率(Precision Rate),召回率(Recall Rate)以及F值(F-Measure)。

1.模型的训练及保存

from sklearn import svm  # sklearn对libsvm的封装
from sklearn.datasets import load_svmlight_file  # 载入libsvm格式文件
如果想永久保存该模型,使用joblib
from sklearn.externals import joblib

首先载入训练样本矩阵格式数据,并使用fit进行适配,然后进行预测,代码很简明:

X_train, y_train = load_svmlight_file("matrix/train_matrix.csv")
clf = svm.SVC(gamma=0.01, C=5, verbose=True)
clf.fit(X_train, y_train)
joblib.dump(clf, 'model_save/train_model.m')  # 永久保存

对于SVM中的参数,gamma和C是最关键的两个参数,它们的确定可以用程序在2*10^-5~2*10^5之间遍历得到。

2.对样本的预测

X_test, y_test = load_svmlight_file("matrix/test_matrix.csv")
clf = joblib.load("model_save/train_model.m")
pred = clf.predict(X_test)
#print accuracy_score(y_test, pred)
#print precision_recall_fscore_support(y_test, pred)
#print precision_recall_curve(y_test, pred)
print 'precision:{0:.3f}'.format(precision_score(y_test, pred))
print 'racall:{0:.3f}'.format(recall_score(y_test, pred))
print 'fscore:{0:.3f}'.format(f1_score(y_test, pred))

结果:
result.png

有件有意思的事情,当我使用从真实数据中抽出的负样本作为训练的负样本时,得到的结果极其的差,差到什么程度呢?预测的结果全是1,我的导师认为这么小的概率根本不可能,一定是我的程序有问题(但我的观点是这不能用独立事件的连乘算概率),图中的结果是我拿人民日报的结果当负样本得到的结果,目前正在研究为什么差异如此之大。

三.文本特征提取和向量化

在(二)中,我已经能获取每个词条在百度搜索下的结果。我将所有的可疑词条的百度搜索结果保存为文件。每一行文本是一个词条的搜索结果。例如,我有728个可以词条,那么我将保存728行文本,现在我们要提取出每一行文本中的特征词。

接下来的操作依次是:

  1. 标记正负样本并下载它们的全部文本
  2. 对文本进行分词
  3. 通过Tf-Idf、词频、CHI、或是信息增益等方法取出特征词
  4. 将特征词向量化

获取正负样本

我使用手工的方法,在近3000个样本分离出了150个负样本,也就是诸如’asdf’之类看上去很不正常的名称,正样本就选取带’有限公司’的公司名,并使用(二)中的方法,将正负样本的的网页搜索结果解析出来的 文本保存下来。

  分词  

  中文分词我使用的是jieba,jieba有多种切词模式,还支持自定义停用词和idf词库,如果你使用的是jieba.analyse这个库,它支持tfidf和textRank两种特征,在我的使用过程中有一个很不爽的地方是,如果你仅仅使用jieba.cut,那么在原文本中包含的多种特殊符号将令人头疼(当然你也可以用正则消除掉),而一旦你使用jieba.analyse,你会发下它已经自动过滤了这些词,可是它已经使用了tf-idf或是textRank,一句话:如果你仅仅想用它来分词,提取特征的事情后续由自己来做,那么jieba.analyse会令人讨厌的先给你的词预筛选一遍。这里我topK设置为前10000个词,基本上不会筛掉词了。

分词代码段:

def extract_tag(text_file, tag_file):
    with open(text_file, 'r') as tf:
        for text in tf:
            utf8_text = text.decode('utf-8', 'ignore')
            #print utf8_text
            seg_list = jieba.cut(utf8_text, cut_all=True)
            clean_text = " ".join(seg_list)
            jieba.analyse.set_stop_words("extra/stop_words.dict")
            print '\n'
            tags = jieba.analyse.textrank(clean_text, topK=10000, withWeight=False, allowPOS=('ns', 'n', 'vn', 'v'))
            print(" ".join(tags))
            mstr = " ".join(tags)
            mlist = mstr.split()
            mlist = list(set(mlist))
            with open(tag_file, 'a') as f:
                for item in mlist:
                    utf8_item = item.encode('utf-8', 'ignore')
                    f.write(utf8_item+'\t')
                f.write('\n')
            f.close()
    tf.close()

这里我得到一个tag_file,每一行有若干个词,代表这一个文本的特征集合,下面要做的事就是提取特征。

特征提取
我没有使用Tf-Idf,是因为它存在的一个严重缺陷是:假如一个词仅仅在某个类中出现过多次,那么其实该词是该类的一个非常好的特征,但根据Tf-Idf的机制,该词由于出现过太多次反而权重不高,在本次中,我目前使用的仅仅是词频,未来可能尝试其他方法。

向量化

所谓向量化,即对存在的词,每个词赋予其一个维度,然后对正负样本的每一行特征,按照其是否在特征向量中的某一维,决定该行特征是0还是非0。

我的做法是:

  1. 先将正负样本词库整合,并计算每个词出现的次数t,假设出现次数最大的词出现次数为max,每个词的权重即为t/max,导师建议使用每个维度的最大次数而非全局,之后可以试试看。
  2. 构造正负样本矩阵并保存
  3. 构造测试样本的矩阵,矩阵的权重来源于训练样本。

代码如下:

合并词库:

def merge_dict(pos_tag, neg_tag):
    """
    Parameter
    -------
    pos_tag: file of pos tag
    neg_tag: file of neg tags

    Return
    -----
    mixed tags list
    """
    words = []
    with open(pos_tag, 'r') as pt:
        for line in pt:
            word = line.split()
            for t in word:
                words.append(t)
    with open(neg_tag, 'r') as nt:
        for line in nt:
            word = line.split()
            for t in word:
                words.append(t)
    tag_list = list(set(words))
    print tag_list
    return tag_list

构造正负样本矩阵:

def get_libsvm_data(pos_tag, neg_tag, word_list, matrix_file):
    fmatrix = open(matrix_file, 'a+')
    with open(pos_tag, 'r') as pt:
        for line in pt:
            tag = []
            word_flag = []
            word = line.split()
            if len(word) == 0:
                continue
            word = list(set(word))
            tag.append('+1')
            for t in word:
                p = word_list.index(t)
                word_flag.append(p)
            word_flag.sort()
            for t in word_flag:
                tag.append(' '+str(t)+':'+'1')
            mstr = ''.join(tag)
            fmatrix.write(mstr)
            fmatrix.write('\n')
    with open(neg_tag, 'r') as nt:
        for line in nt:
            tag = []
            word_flag = []
            word = line.split()
            if len(word) == 0:
                continue
            word = list(set(word))
            tag.append('-1')
            for t in word:
                p = word_list.index(t)
                word_flag.append(p)
            word_flag.sort()
            for t in word_flag:
                tag.append(' '+str(t)+':'+'1')
            mstr = ''.join(tag)
            fmatrix.write(mstr)
            fmatrix.write('\n')

构造测试样本矩阵:

def shape_testdata(pos_test_tag, neg_test_tag, word_list, matrix_file):
    fmatrix = open(matrix_file, 'a+')
    with open(pos_test_tag, 'r') as pt:
        for line in pt:
            tag = []
            last_flag = 0  # if the last has value
            word_flag = []
            word = line.split()
            if len(word) == 0:
                continue
            word = list(set(word))
            tag.append('+1')
            for t in word:
                if t in word_list:
                    p = word_list.index(t)
                    if p == len(word_list):
                        last_flag = 1
                    word_flag.append(p)
            word_flag.sort()
            if len(word_flag) != 0:
                for t in word_flag:
                    tag.append(' '+str(t)+':'+'1')
                if last_flag == 0:
                    tag.append(' '+str(len(word_list))+':'+'0')
            mstr = ''.join(tag)
            fmatrix.write(mstr)
            fmatrix.write('\n')

    with open(neg_test_tag, 'r') as nt:
        for line in nt:
            tag = []
            word_flag = []
            last_flag = 0
            word = line.split()
            if len(word) == 0:
                continue
            word = list(set(word))
            tag.append('-1')
            for t in word:
                if t in word_list:
                    p = word_list.index(t)
                    if p==len(word_list):
                        last_flag = 1
                    word_flag.append(p)
            word_flag.sort()
            if len(word_flag) != 0:
                for t in word_flag:
                    tag.append(' '+str(t)+':'+'1')
                if last_flag == 0:
                    tag.append(' '+str(len(word_list))+':'+'0')
            mstr = ''.join(tag)
            fmatrix.write(mstr)
            fmatrix.write('\n')

于是我们成功得到了训练样本和测试样本的矩阵,中间出现过一个bug是:训练样本和测试样本矩阵维度不同,这是由于记录时自动去除了值为0的维度,因此假如在测试样本中,未出现训练样本的末尾的维度,测试样本的维度将小于训练样本。改进是判断最后一维是否在测试样本中出现。未出现则注’0′

以下为矩阵格式(其实是libsvm的格式):

QQ截图20160309210229

二 .抓取网页文本数据

第一次接触“爬虫”这个词时,就觉得“看上去吊吊的”,记得当时我一室友三天两头的让我学爬虫,好给他下载****,话不多说,今天记录一下我爬取百度搜索结果的过程。

我需要做的事情是:对每一个上一篇中的得到的可疑词条,进行百度检索,提取所有检索结果中的公司简介,如下图所示:

QQ截图20160309173851

由于第一次接触爬虫(事实上接触Python也不久=。=),在解析网页上,我盲目的试了很多种方法,包括使用Python自带的HTMLParser,使用正则表达式等等,均用的不太顺手,可能需要一段学习时间,这时候我选择了BeautifulSoup,并简要的学习了它的官方文档。如何评价它呢?两个字:优雅!至少对我这样的新手,我上面的需求仅仅几行代码就搞定了。

具体步骤:

首先需要使用百度搜索

导入requests

import requests

下载百度搜索结果整页的html

def download_html(company_name):
    download html

    Parameters
    ---------
    company_name: company name need to be detected

    Returns
    ------
    utf8_content: the web content encode in utf-8

    key = {'wd': company_name}
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko'}
    web_content = requests.get(http://www.baidu.com/s?;, params=key, headers=headers)
    utf8_content = web_content.text
    return utf8_content

接下来就是对html格式里的数据进行解析了,我观察到,我需要的数据都存在于一个class = ‘c-abstract’的div块内部,这时候该让BeautifulSoup显示它的威力了

# Get the wanted text
soup = BeautifulSoup(html) #Get an object of bs
text = []
for tag in soup.find_all(attrs={class:c-abstract}):
    text.append(tag)

结果如下:


信诺公司致力于用信息技术提高推动行业发展和社会进步,推动政府、公众媒体、企业的互联网应用和信息化建设,是具备国际水准的移动互联网技术和应用方案提供商。信诺集团...温馨提示:该网站是 北京信诺网拓营销顾问有限公司在传众网的免费网站,如果您是该单位负责人,请 点击这里 登陆后申请个性化二级域名并更新您的企业资料后,即可删除你...公司名称: 北京信诺网拓营销顾问有限公司 公司地址: 公司网站: 联系电话: 联系邮箱: 公司编辑 恭喜您,提交成功! 您的编辑正在审核中,1个工作日内,会以邮...北京信诺网拓营销顾问有限公司位于广东 广州 。主营产品:新媒体,云服务,app开发... 北京信诺网拓营销顾问有限公司信诺集团致力于用信息技术推动行业发展和社会进步,推... 简介: 北京信诺网拓营销顾问有限公司是从事互联网、移动互联网产品开发、技术支持、运营维护、推广营销等一系列集... T 友情链接 信诺网拓 机窝应用市场 ...真实北京信诺网拓营销顾问有限公司产品经理工资待遇,在职员工或曾在职员工真实分享,更多北京信诺网拓营销顾问有限公司工资待遇,面试题,面经分享,公司评价尽在职业圈。北京信诺网拓营销顾问有限公司优势广告资源在广告买卖网的集中展示... 公司名: 北京信诺网拓营销顾问有限公司 所在地: 北京市 丰台区 信誉度: 好评率: 100% 认证...北京:010-84675419 华南营销中心:0731-82557982 手机:13810292520 北京信诺必拓企业管理顾问有限公司 京ICP备09115053号-1...北京信诺网拓营销顾问有限公司招聘,58同城官方网站,提供最新招聘信息、公司地址、电话、工资待遇、公司介绍等信息;我公司诚聘:“广告销售经理”、“市场经理”、“...您是北京信诺网拓营销顾问有限公司的雇员吗?欢迎提交您的职位与薪酬情况,帮助求职者更好的了解北京信诺网拓营销顾问有限公司的工资薪酬待遇概况

一. 数据整理

我实习的第一个任务是从带有脏数据的公司名称数据字典中,分类出正确的数据。

超硅光电技术有限公司 超硅光电
adsfasfd
吖咪网络科技有限公司 吖咪
合禾品牌

上表中[adsfasfd]就属于脏数据,该如何清洗呢?这里存在2个问题:

  1.  每个公司名称的文本长度太短,包含的信息量有限。
  2.  即使手工分类,有些公司名称例如[亿奔],如果不经检索,人脑也很难判断该名称是否属于公司。

 

总之就是数据不足,因此我采用的策略是:

  1. 简单整理数据
  2. 抓取每个词条在搜索引擎(此处用的是百度)上得到的结果,结合文本分类进行判定

 

利用规则对公司名称字典数据进行初步清洗,规则很简单,去掉所有带“有限公司”字眼的公司名,并将剩余词条中的“ , 》 !删去,代码如下:


def data_clean(company_path, symbol_path):

    """
    clean the data

    Parameters
    ---------
    company_path: Path of company
    symbol_path: Path of symbols

    Returns
    -------
    suspicious_name: The sorted series of company
    company:the name of company

    """
    # Load the symbols
    for line in open(symbol_path):
        symbols = line.split(',')

    # Load the name of company
    company = []
    for line in open(company_path):
        fields = line.replace('\n', '').split('\t')
        company.append(fields[0])

    # Encode the company
    for text in company:
        mylist = list(text)
        for x in mylist:
            if x in symbols:
                mylist = list(text)
                mylist.remove(x)
                text = ''.join(mylist)

    company_with_end = copy.deepcopy(company)
    suspicious_name = []
    correct_name = []

    # flit company which have supposed end
    count = 0
    for company in company_with_end:
        mylist = list(company)
        mystr = ''.join(mylist)
        correct_end = '有限公司'
        if correct_end not in mystr:
            suspicious_name.append(company)
            utf8_str = unicode(company, 'utf-8')
            sus_company = utf8_str.encode('gbk', 'ignore')
            print sus_company
        else:
            correct_name.append(company)
    return suspicious_name, correct_name

我们先对全部词条进行了去特殊符号,然后得到了不带“有限公司”的可疑词条集合,该集合正是我们需要分类的部分。

接下来我们将爬取网页中的文本。