统计常用字的一种方法

最近工作中需要一个常用字集合,网上找了些,都不太满意,所以打算自己做一个。统计常用字最难的地方就是数据收集这块,想到后台一直在网上爬东西,觉得可以利用一下,这样最难的问题就解决了。

废话少说,整体流程如下:

1.使用爬虫从网上抓取海量网页数据,采用utf-16格式保存成文件。

2.统计文件中每个字的次数,排序,生成一个log文件,该文件输出了每个字及其出现的次数,另一个文件就是常用字库啦。


一、抓取网页

采用scrapy抓取网页,这是一个开源的python库,简单易用,扩展性强,虽然我对html啥的不太熟,但还是凑活完成功能。该库的用法网上有介绍,但是个人觉得官网的介绍最给力了。在抓取网页中,主要碰到了3个问题:初始url怎么选、网页编码如何确定、重复url如何去除。

1. 初始url选择:主要看你关注哪个方面的常用字了,我的方法很简单,在百度上搜关键字,然后把链接作为初始url。

2.网页编码如何确定:网上说的方法主要有3种:一是从response对象获取编码方式,二是从网页的meta中的charset获得编码,三是采用codedet库自动分析得到,我采用第三个,因为觉得它最简单也最靠谱。

3.重复url如何去除:由于抓取的链接可能会有互相引用,导致出现重复的url,这样对常用字的统计有干扰,因此需要去掉。scrapy自带了去重的功能,但是默认不启用,不知道是出于什么考虑,启用的方法是重载爬虫的一个方法就好。


下面试爬虫的关键代码:

#coding=utf-8
from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
from scrapy.selector import HtmlXPathSelector
from scrapy.item import Item
from datetime import datetime
import chardet
import codecs
from scrapy.http import Request

g_cur_time = datetime.now()
g_html_fp = codecs.open('pages\\' + str(g_cur_time).replace(':', '.'), 'wb', 'utf-16')
class KeySpider(CrawlSpider):
	name = 'keywords'
	rules = (
		Rule(SgmlLinkExtractor(), 'parse_page', follow = True),#获得子网页的url接着往下爬,主要是参数follow,每抓到一个网页都会调用parse_page函数
	)
	start_urls = [
		#电脑
		r'http://www.baidu.com/s?tn=baiduhome_pg&ie=utf-8&bs=%E5%B9%BF%E5%91%8A&f=8&rsv_bp=1&rsv_spt=1&wd=%E7%BE%8E%E5%A5%B3&rsv_sug3=17&rsv_sug=0&rsv_sug1=11&rsv_sug4=5748&inputT=26359',
		#淘宝
		r'http://www.baidu.com/s?wd=%E6%B7%98%E5%AE%9D&rsv_spt=1&issp=1&rsv_bp=0&ie=utf-8&tn=baiduhome_pg&rsv_sug3=4&rsv_sug=0&rsv_sug1=2&rsv_sug4=518',
		#腾讯
		r'http://www.baidu.com/s?tn=baiduhome_pg&ie=utf-8&bs=%E9%BB%91%E5%AE%A2&f=8&rsv_bp=1&rsv_spt=1&wd=%E8%85%BE%E8%AE%AF&rsv_sug3=7&rsv_sug=0&rsv_sug1=6&rsv_sug4=237&inputT=3017',
		#游戏
		r'http://www.baidu.com/s?wd=%E6%B8%B8%E6%88%8F&rsv_spt=1&issp=1&rsv_bp=0&ie=utf-8&tn=baiduhome_pg&rsv_sug3=5&rsv_sug=0&rsv_sug1=3&rsv_sug4=708',
		#外挂
		r'http://www.baidu.com/s?tn=baiduhome_pg&ie=utf-8&bs=%E5%A4%96%E6%8C%82&f=8&rsv_bp=1&rsv_spt=1&wd=%E5%A4%96%E6%8C%82&rsv_sug3=6&rsv_sug=1&rsv_sug1=4&rsv_sug4=306&inputT=2124',
		#网购
		r'http://www.baidu.com/s?tn=baiduhome_pg&ie=utf-8&bs=%E9%BB%91%E5%AE%A2&f=8&rsv_bp=1&rsv_spt=1&wd=%E6%81%B6%E6%84%8F%E7%BD%91%E7%AB%99&rsv_sug3=22&rsv_sug=0&rsv_sug1=13&rsv_sug4=1033&inputT=12260',
		#美女
		r'http://www.baidu.com/s?tn=baiduhome_pg&ie=utf-8&bs=%E6%81%B6%E6%84%8F%E7%BD%91%E7%AB%99&f=8&rsv_bp=1&rsv_spt=1&wd=%E7%BD%91%E6%B8%B8&rsv_sug3=4&rsv_sug=0&rsv_sug1=3&rsv_sug4=228&inputT=2177',
	]
	def parse_page(self, response):
		global g_html_fp
		cs = chardet.detect(response.body)#检测编码,保存
		content = response.body.decode(cs['encoding'], 'ignore')
		g_html_fp.write(content)
		
	def make_requests_from_url(self, url):
		return Request(url, dont_filter=False)#scrapy的为True,然后就不会去重了,这里我们改为False
然后就想到了怎么结束了,不能一直爬下去啊,找了一下其实是参数DEPTH_LIMIT 来决定的,它控制爬虫走的深度,这个参数写到settings.py文件中,表示爬几层。默认为0,表示无限制。

我用上面的初始网址爬了一夜都没爬完,最后强关,生成了一个6G的文件,伤不起啊,数据太多了。

二、统计常用字

这个就简单了,刚开始打算用python写的,那个难受啊,各种查文档,后来改用C++,世界都清净了。

// libgencommonword.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <locale.h>
#include <map>
#include <algorithm>
#include <vector>
using std::vector;
typedef std::pair<unsigned short int, __int64> WordPair;
void GeneratorLog(vector<WordPair>& data){
	FILE* fp = NULL;
	if(fopen_s(&fp, "charset.log", "w")){
		printf("create log file error\n");
		return;
	}
	std::for_each(data.begin(), data.end(), [&](const WordPair& item){
		wchar_t buffer[2] = {item.first};
		char buffer_mbc[5];
		if(static_cast<size_t>(-1) == wcstombs(buffer_mbc, buffer, 5))
			strcpy_s(buffer_mbc, "null");
		fprintf(fp, "%04X,%s,%I64d\r\n", item.first, buffer_mbc, item.second);
	});
	fclose(fp);
}
void GenerateLib(vector<WordPair>& data){
	FILE* fp = NULL;
	if(fopen_s(&fp, "charsetlib.dat", "wb")){
		printf("create lib file error.\n");
		return;
	}
	std::for_each(data.begin(), data.end(), [&](const WordPair& item){
		fwrite(&item.first, sizeof(item.first), 1, fp);
	});
	fclose(fp);
}
int _tmain(int argc, _TCHAR* argv[])
{
	setlocale(LC_ALL,"");
	__int64 word_count[65536] = {0};
	FILE* fp = NULL;
	if(argc < 2){
		printf("Usage:this.exe filename\n");
		return -1;
	}
	HANDLE hfile = CreateFile(argv[1],
		GENERIC_READ,
		FILE_SHARE_READ,
		NULL,
		OPEN_EXISTING,
		0, NULL);
	if(INVALID_HANDLE_VALUE == hfile){
		printf("open file error:%s\n", argv[1]);
		return -1;
	}
	unsigned short int ch[2048];
	DWORD readed;
	while(ReadFile(hfile, ch, sizeof(ch), &readed, NULL)){
		if(!readed)
			break;
		readed /= sizeof(ch[0]);
		for(DWORD i = 0; i < readed; i++){
			if(!iswgraph(ch[i]) && ch[i] != 0x20)
				continue;
			word_count[ch[i]] += 1;
		}
	}
	CloseHandle(hfile);

	vector<WordPair> count_vec;
	for(size_t i = 0; i < sizeof(word_count)/sizeof(word_count[0]); i++){
		if(word_count[i])
			count_vec.push_back(WordPair(i, word_count[i]));
	}
	std::sort(count_vec.begin(), count_vec.end(), [](WordPair& item1, WordPair& item2){
		return item1.second > item2.second;
	});
	GenerateLib(count_vec);
	GeneratorLog(count_vec);
	return 0;
}
代码运行完生成两个文件,一个是常用字库,另一个是统计结果,6G的文件还是要跑一会的,估计得几分钟。


参考了不少别人的文章,在此表示感谢,如下一些链接可能对你有帮助:

字符转码的网站:http://bianma.51240.com/

scrapy去重,分析的很好:http://blog.pluskid.org/?p=381

scrapy的官网:http://doc.scrapy.org/en/0.18/

utf-16的编码:http://www.fileformat.info/info/charset/UTF-16/list.htmhttp://www.fileformat.info/info/charset/index.htm


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值