如何用python对文本进行聚类

Python052

如何用python对文本进行聚类,第1张

实现原理:

首先从Tourist_spots_5A_BD.txt中读取景点信息,然后通过调用无界面浏览器PhantomJS(Firefox可替代)访问百度百科链接"http://baike.baidu.com/",通过Selenium获取输入对话框ID,输入关键词如"故宫",再访问该百科页面。最后通过分析DOM树结构获取摘要的ID并获取其值。核心代码如下:

driver.find_elements_by_xpath("//div[@class='lemma-summary']/div")

PS:Selenium更多应用于自动化测试,推荐Python爬虫使用scrapy等开源工具。

# coding=utf-8

"""

Created on 2015-09-04 @author: Eastmount

"""

import time

import re

import os

import sys

import codecs

import shutil

from selenium import webdriver

from selenium.webdriver.common.keys import Keys

import selenium.webdriver.support.ui as ui

from selenium.webdriver.common.action_chains import ActionChains

#Open PhantomJS

driver = webdriver.PhantomJS(executable_path="G:\phantomjs-1.9.1-windows\phantomjs.exe")

#driver = webdriver.Firefox()

wait = ui.WebDriverWait(driver,10)

#Get the Content of 5A tourist spots

def getInfobox(entityName, fileName):

try:

#create paths and txt files

print u'文件名称: ', fileName

info = codecs.open(fileName, 'w', 'utf-8')

#locate input notice: 1.visit url by unicode 2.write files

#Error: Message: Element not found in the cache -

# Perhaps the page has changed since it was looked up

#解决方法: 使用Selenium和Phantomjs

print u'实体名称: ', entityName.rstrip('\n')

driver.get("http://baike.baidu.com/")

elem_inp = driver.find_element_by_xpath("//form[@id='searchForm']/input")

elem_inp.send_keys(entityName)

elem_inp.send_keys(Keys.RETURN)

info.write(entityName.rstrip('\n')+'\r\n') #codecs不支持'\n'换行

time.sleep(2)

#load content 摘要

elem_value = driver.find_elements_by_xpath("//div[@class='lemma-summary']/div")

for value in elem_value:

print value.text

info.writelines(value.text + '\r\n')

time.sleep(2)

except Exception,e:#'utf8' codec can't decode byte

print "Error: ",e

finally:

print '\n'

info.close()

#Main function

def main():

#By function get information

path = "BaiduSpider\\"

if os.path.isdir(path):

shutil.rmtree(path, True)

os.makedirs(path)

source = open("Tourist_spots_5A_BD.txt", 'r')

num = 1

for entityName in source:

entityName = unicode(entityName, "utf-8")

if u'故宫' in entityName: #else add a '?'

entityName = u'北京故宫'

name = "%04d" % num

fileName = path + str(name) + ".txt"

getInfobox(entityName, fileName)

num = num + 1

print 'End Read Files!'

source.close()

driver.close()

if __name__ == '__main__':

main()

可能我很快回答不了你的问题。还需要细细回味一下。

但是我觉得你的问题是一个比较明显的短文本聚类问题,这个问题应该在国际上都是比较难的吧。

如果还涉及到中文,中文的相关处理又不能照抄英文短文本聚类的方法,相关资料更加少了。

我倒是建议你 多看一些短文本聚类相关的文章。

问题一:技术上python矩阵表示的话:你可以使用python包,如下:

from numpy import matrix

A = matrix( [[1,2,3],[11,12,13],[21,22,23]])

这样你需要额外规定化:行i表示文档编号i的文档,列j表示词j出现次数,A[i][j]表示在文档i中词j的出现频率

或者

如同那篇文章所说的采用dict表示法:A = [{'额外':1},{'每天':1,'回帖':1},......]表示整个文档集合。

问题二:如同这样的问题本质一样,短文本聚类是否还适合传统的分词,去除副词...等处理步骤,

如何选择合适的模型来表示这类问题,我觉得你还是参考一些这方面的文章,最好中文的。

比如现在很火的微博,也会有好多的人尝试对其中成干上万评论进行聚类。很多进行二类或者三类聚类/分类:支持-中立-反对。

论坛的评论应该很早以前就有研究聚类/分类.我觉得去那里参考会更好.如果不是特别面向指定目的的聚类,我觉得采用一些使用宽泛的方法就行了。感觉结果不会很好。

问题三:EM算法感觉像纯数学的东西,学术功底不够深,我也不好发表看法。

感觉这个问题的本质已经超出我的知识范畴。最简单文档聚类无非:分词-文本预处理[同义词之类]-文档与词计频矩阵表示-(TF-IDF预处理)-kmeans跑起来-输出结果.