怎样借助Python爬虫给宝宝起个好名字

2019-03-31更新:

代码的python3简化版本:

https://github.com/peiss/chinese-name-score/tree/master/chinese-name-score/python3

代码的视频讲解(我的付费视频课程中的一节):

https://www.iqiyi.com/v_19rsj1yvy8.html


每个人一生中都会遇到一件事情,在事情出现之前不会关心,但是事情一旦来临就发现它极其重要,并且需要在很短的时间内做出重大决定,那就是给自己的新生宝宝起个名字。

因为要在孩子出生后两周内起个名字(需要办理出生证明了),估计很多人都像我一样,刚开始是很慌乱的,虽然感觉汉字非常的多随便找个字做名字都行,后来才发现真不是随便的事情,怎么想都发现不合适,于是到处翻词典、网上搜、翻唐诗宋词、诗经、甚至武侠小说,然而想了很久得到的名字,往往却受到家属的意见和反对,比如不顺口、和亲戚重名重音等问题,这样就陷入了重复寻找和否定的循环,越来越混乱。

于是我们再次回到网上各种搜索,找到很多网上给出的“男宝宝好听的名字大全”之类的文章,这些文章一下子给出几百上千个名字,看的眼花缭乱没法使用。而有不少的测名字的网站或者APP,输入名字能给出八字或者五格的评分,这样的功能感觉还挺好的能给个参考,然而要么我们需要一个个名字的输入进行测试、要么这些网站或者APP自身的名字很少、要么不能满足我们的需求比如限定字、要么就开始收费,到最后也找不到一个好用的。

于是我想做这么一个程序:

  1. 主要的功能,是给出批量名字提供参考,这些名字是结合宝宝的生辰八字算出来的;
  2. 自己可以扩充名字库,比如网上发现了一批诗经里的好名字,想看看怎么样,添加进去就能用;
  3. 可以限定名字的使用字,比如有的家族谱有限定,当前是“国”字辈,名字中必须有“国”字;
  4. 名字列表可以给出评分,这样倒排后就可以从高分往低分来看名字;

通过这种方式可以得到一份符合自己孩子生辰八字、自己的家谱限制、以及自己喜好的名字列表,并且该列表已经给出了分数用于参考,以此为基准我们可以挨个琢磨找出心仪的名字。当然如果有新的想法,随时可以把新的名字添加到词库里面,进行重新计算。

程序的代码结构

代码介绍:

  • /chinese-name-score 代码根目录
  • /chinese-name-score/main 代码目录
  • /chinese-name-score/main/dicts 词典文件目录
  • /chinese-name-score/main/dicts/names_boys_double.txt 词典文件,男孩的双字名字
  • /chinese-name-score/main/dicts/names_boys_single.txt 词典文件,男孩的单字名字
  • /chinese-name-score/main/dicts/names_girls_single.txt 词典文件,女孩的双字名字
  • /chinese-name-score/main/dicts/names_grils_double.txt 词典文件,女孩的单字名字
  • /chinese-name-score/main/outputs 输出数据目录
  • /chinese-name-score/main/outputs/names_girls_source_wxy.txt 输出的示例文件
  • /chinese-name-score/main/scripts 一些对词典文件做预处理的脚本
  • /chinese-name-score/main/scripts/unique_file_lines.py 设定词典文件,对词典中的名字去重和去空白行
  • /chinese-name-score/main/sys_config.py 程序的系统配置,包含爬取得目标URL、词典文件路径
  • /chinese-name-score/main/user_config.py 程序的用户配置,包括宝宝的年月日时分性别等设定
  • /chinese-name-score/main/get_name_score.py 程序的运行入口

使用代码的方法:

  1. 如果没有限定字,就找到词典文件names_boys_double.txt和names_grils_double.txt,可以在这里添加自己找到的一些名字列表,按行分割添加在最后即可;
  2. 如果有限定字,就找到词典文件names_boys_single.txt和names_girls_single.txt,在这里添加自己预先中意的单个字列表,按行分割添加在最后即可;
  3. 打开user_config.py,进行配置,配置项见下一节;
  4. 运行脚本get_name_score.py
  5. 在outputs目录中,查看自己的产出文件,可以复制到Excel,进行排序等操作;

程序的配置入口

程序的配置如下:

# coding:GB18030

"""
在这里写好配置
"""

setting = {}

# 限定字,如果配置了该值,则会取用单字字典,否则取用多字字典
setting["limit_world"] = "国"
# 姓
setting["name_prefix"] = "李"
# 性别,取值为 男 或者 女
setting["sex"] = "男"
# 省份
setting["area_province"] = "北京"
# 城市
setting["area_region"] = "海淀"
# 出生的公历年份
setting['year'] = "2017"
# 出生的公历月份
setting['month'] = "1"
# 出生的公历日子
setting['day'] = "11"
# 出生的公历小时
setting['hour'] = "11"
# 出生的公历分钟
setting['minute'] = "11"
# 结果产出文件名称
setting['output_fname'] = "names_girls_source_xxx.txt"

根据配置项setting[“limit_world”],系统自动来决定选用单字词典还是多字词典:

  • 如果设置了该项,比如等于“国”,那么程序会组合所有的单字为名字用于计算,比如国浩和浩国两个名字都会计算;
  • 如果不设置该项,保持空字符串,则程序只会读取*_double.txt的双字词典

程序的原理

这是一个简单的爬虫。大家可以打开http://life.httpcn.com/xingming.asp网站查看,这是一个POST表单,填写需要的参数,点提交,就会打开一个结果页面,结果页面的最下方包含了八字分数和五格分数。

如果想得到分数,就需要做两件事情,一是爬虫自动提交表单,获取结果页面;二是从结果页面提取分数;

对于第一件事情,很简单,urllib2即可实现(代码在/chinese-name-score/main/get_name_score.py):

    post_data = urllib.urlencode(params)
    req = urllib2.urlopen(sys_config.REQUEST_URL, post_data)
    content = req.read()

这里的params是个参数dict,使用这种方式,就进行了POST带数据的提交,然后从content得到了结果数据。

params的参数设定如下:

    params = {}
    
    # 日期类型,0表示公历,1表示农历
    params['data_type'] = "0"
    params['year'] = "%s" % str(user_config.setting["year"])
    params['month'] = "%s" % str(user_config.setting["month"])
    params['day'] = "%s" % str(user_config.setting["day"])
    params['hour'] = "%s" % str(user_config.setting["hour"])
    params['minute'] = "%s" % str(user_config.setting["minute"])
    params['pid'] = "%s" % str(user_config.setting["area_province"])
    params['cid'] = "%s" % str(user_config.setting["area_region"])
    # 喜用五行,0表示自动分析,1表示自定喜用神
    params['wxxy'] = "0"
    params['xing'] = "%s" % (user_config.setting["name_prefix"])
    params['ming'] = name_postfix
    # 表示女,1表示男
    if user_config.setting["sex"] == "男":
        params['sex'] = "1"
    else:
        params['sex'] = "0"
        
    params['act'] = "submit"
    params['isbz'] = "1"

第二件事情,就是从网页中提取需要的分数,我们可以使用BeautifulSoup4来实现,其语法也很简单:

    soup = BeautifulSoup(content, 'html.parser', from_encoding="GB18030")
    full_name = get_full_name(name_postfix)
    
    # print soup.find(string=re.compile(u"姓名五格评分"))
    for node in soup.find_all("div", class_="chaxun_b"):
        node_cont = node.get_text()
        if u'姓名五格评分' in node_cont:
            name_wuge = node.find(string=re.compile(u"姓名五格评分"))
            result_data['wuge_score'] = name_wuge.next_sibling.b.get_text()
        
        if u'姓名八字评分' in node_cont:
            name_wuge = node.find(string=re.compile(u"姓名八字评分"))
            result_data['bazi_score'] = name_wuge.next_sibling.b.get_text()

通过该方法,就能对HTML解析,提取八字和五格的分数。

运行结果事例

1/1287 李国锦	姓名八字评分=61.5	姓名五格评分=78.6	总分=140.1
2/1287 李国铁	姓名八字评分=61	姓名五格评分=89.7	总分=150.7
3/1287 李国晶	姓名八字评分=21	姓名五格评分=81.6	总分=102.6
4/1287 李鸣国	姓名八字评分=21	姓名五格评分=90.3	总分=111.3
5/1287 李柔国	姓名八字评分=64	姓名五格评分=78.3	总分=142.3
6/1287 李国经	姓名八字评分=21	姓名五格评分=89.8	总分=110.8
7/1287 李国蒂	姓名八字评分=22	姓名五格评分=87.2	总分=109.2
8/1287 李国登	姓名八字评分=21	姓名五格评分=81.6	总分=102.6
9/1287 李略国	姓名八字评分=21	姓名五格评分=83.7	总分=104.7
10/1287 李国添	姓名八字评分=21	姓名五格评分=81.6	总分=102.6
11/1287 李国天	姓名八字评分=22	姓名五格评分=83.7	总分=105.7
12/1287 李国田	姓名八字评分=22	姓名五格评分=93.7	总分=115.7

有了这些分数,我们就可以进行排序,是一个很实用的参考资料。

友情提示

  1. 分数跟很多因素有关,比如出生时刻、已经限定的字、限定字的笔画等因素,这些条件决定了有些名字不会分数高,不要受此影响,找出相对分数高的就可以了;
  2. 目前程序只能抓取一个网站的内容,地址是http://life.httpcn.com/xingming.asp
  3. 本列表仅供参考,看过一些文章,历史上很多名人伟人,姓名八字评分都非常低但是都建功立业,名字确实会有些影响但有时候朗朗上口就是最好的;
  4. 从本列表中选取名字之后,可以在百度、人人网等地方查查,以防有些负面的人重名、或者起这个名字的人太多了烂大街;
  5. 八字分数是中国传承,五格分数是日本人近代发明的,有时候也可以试试西方的星座起名法,并且奇怪的是八字和五个分数不同网站打分相差很大,更说明了这东西只供参考;

本文的代码已上传到github:https://github.com/peiss/chinese-name-score

附注:有些朋友不会运行程序,但是想得到宝宝起名结果列表,可以QQ693609645联系我,我帮你运行一份结果,收取少量费用

本文地址:http://crazyant.net/2076.html,转载请注明来源。

 

Firefox数据采集插件大全

本文介绍了使用firefox进行数据采集的一些小窍门、一些数据采集建议和一些优秀的用于数据采集的firefox插件。

实时操作浏览器DOM的一些注意事项

firefox的插件能够实时的对展现出来的网页进行DOM操作和查看,请注意通过firefox的firebug还有chrome的”查看元素”功能查看到的都不是页面最初的源码,而是经过浏览器的一些修改后的结果,比如浏览器会对收到的源码作清理操作,作执行javascript操作。比如对于firefox浏览器,它会自动的给table元素加上<tbody>标签。然而在数据采集时候,比如使用scrapy时,并没有经过浏览器这一步骤的处理,所以如果采集规则中带有<tbody>标签,显然会解析失败。

因此,使用firefox或者xpath做数据采集规则设计和处理时,要注意:

  • 先禁用firefox的javascript执行引擎,然后再对DOM做提取xpath的操作,这样的xpath才能用于scrapy框架中
  • 不要使用xpath的完全绝对路径,比如/html/body/div/a/href这样的,最好使用一些相对的定位方法(比如id, class, width等),或者其他的一些特性比如contains(@href, ‘image’)
  • 在你的xpath中永远不要出现<tbody>标签,除非你确定目标站有这个标签

用于数据采集的firefox插件

Firebug

地址:http://getfirebug.com/

Firebug是一个web开发者大都知道的工具,它在web采集中也非常的有用。当你鼠标移动到一个页面元素上时,firebug能够让你快速查看其html代码,这样当你构建一个元素的xpath路径时非常的有用。

20130930114533

XPather

地址:https://addons.mozilla.org/zh-CN/firefox/addon/xpather/

当你写好了一个xpath,使用该插件能够在该页面检测一下是否正确,是否能正常工作。

XPath Checker

地址:https://addons.mozilla.org/zh-CN/firefox/addon/xpath-checker/

另外一个firefox插件,能够让你在页面上检测写的xpath是否正确。

Tamper Data

地址:https://addons.mozilla.org/zh-CN/firefox/addon/tamper-data/

一个插件,能够让你修改由firefox发送的HTTP头,Firebug也能够查看HTTP头但不能修改。这个功能很强大,能直接绕过页面的javascript检测直接将参数提交给服务器。

Firecookie

地址:https://addons.mozilla.org/zh-CN/firefox/addon/firecookie/

使用Firecookie很方便的对cookie进行查看和管理,使用该插件能够创建一个新的cookie,删除已有的cookie,查看现有网站的cookie列表,管理cookie权限等很多操作。

HttpFox

地址:https://addons.mozilla.org/en-US/firefox/addon/httpfox/

对HTTP的发送、接受、参数、cookie进行查看、修改、重新发送的插件

20130930115530

Edit Cookies

地址:https://addons.mozilla.org/en-US/firefox/addon/edit-cookies/?src=search

在线更新、新增、删除cookie插件,不需要页面刷新或者修改txt文件。Edit Cookies提供了一个界面用于对cookie的操作。

20130930120232

Tamper Data

地址:https://addons.mozilla.org/en-US/firefox/addon/tamper-data/?src=search

使用tamperdata能够查看和修改浏览器的HTTP/HTTPS头和发送的POST数据。比如对HTTP的发送接收信息进行跟踪和调试,或者对提交的POST数据进行修改。

Live HTTP Headers

地址:https://addons.mozilla.org/en-US/firefox/addon/live-http-headers/?src=search

查看HTTP headers的插件

插件的选择

对于大部分静态页面来说,使用firebug、xpath、XPath Checker就能够设计一套解析规则,设计采集流程。但是对于大部分动态网站来说,很多内容都是javascript加载交互的,就需要进行HTTP头、cookie的分析,比如对于新浪微博的模拟登陆,就需要实时的监控其异步交互过程,这时就需要HttpFox、Tamper Data等插件。更特别的,有时候需要解析网站的javascript代码,可以使用webkit开元库模拟一个浏览器,来对页面做动态解析,不过性能会降低些,可以统一作权衡。

转载请注明来源:http://crazyant.net/2013/09/30/firefox%E6%95%B0%E6%8D%AE%E9%87%87%E9%9B%86%E6%8F%92%E4%BB%B6%E5%A4%A7%E5%85%A8/

数据采集简单示例:采集爱帮网电话号码

爱帮网单个网址:http://www.aibang.com/detail/17881112-420243957

截图:

QQ截图20120609171133

本文采集该页面的标题和2个电话号码,具体的python代码:

# -*- coding: UTF-8 -*-
'''
Created on 2012-6-9
@author: crazyant
'''

#导入urllib2库,用于获取网页
import urllib2

#使用开源库Webscraping库的xpath模块
from Webscraping import xpath,common

#首先,发送请求到爱帮网的一个页面,该页面含有地址
req = urllib2.Request('http://www.aibang.com/detail/17881112-420243957')

#获得响应
reponse = urllib2.urlopen(req)

#将响应的内容存入html变量
html = reponse.read()

#以下抓取页面的标题
title = xpath.search(html, '//div[@class="ppc_title"]/h1[1]')

print '标题:'
#这里要输出中文,因此采用common的to_unicode输出
print common.to_unicode(title[0], 'utf-8')

#使用xpath得到电话号码的节点
tel = xpath.search(html, '//dl[@class="detail_list"]/dd[@class="fb"]')

#使用正则拆分数字
import re
m = re.search(r'([\d-]+)\s([\d-]+)', tel[0])
#如果匹配,输出两个单个电话号码
print '电话号:'
if m is not None:
    for t in m.groups():
        print t

 

运行结果:

标题:
坊上人清真饭庄(高新店)
电话号:
029-88222668
029-88226458

其中主要用到了以下模块:

  • xpath:用于使用路径的方法找到节点
  • re:正则表达式模块,用于拆分电话号码(其实字符串函数也可以)
  • urllib2:用于请求指定URL的页面内容,存于字符串然后分析
  • webscraping 库的common模块:用于将获取到得中文文本转成unicode编码,这样才能够输出

数据采集必备知识-php计划任务的实现

站点如果做的多了,难免要发些伪原创的文章,文章的来源必然来源于网络采集,对于采集这里不详述,我自己用的是”Simple HTML DOM”,见我另一篇关于他的介绍:

数据采集利器-PHP用DOM方式处理HTML之《Simple HTML DOM》

数据采集的话,当然可以人工触发,就是每天运行一下脚本,可是这显然不是很完美,如果抓取可以自动定时获取,那么人工运行可执行页面也就省下来了。

其实php有个概念叫计划任务,可以定时运行某程序,比如数据库备份,更新缓存,生成静态页面,生成网站地图等。在采集里面的运用,就是自动采集数据,然后保存到数据库,比如每天凌晨3点运行一次。

以下是PHP用计划任务实现无人自动采集的介绍。

用到了3个函数:

1、ignore_user_abort(setting);

说明:ignore_user_abort() 函数设置与客户机断开是否会终止脚本的执行。本函数返回 user-abort 设置的之前的值(一个布尔值)。

参数:setting 可选。如果设置为 true,则忽略与用户的断开,如果设置为 false,会导致脚本停止运行。如果未设置该参数,会返回当前的设置。

2、void set_time_limit ( int $seconds )

说明:设置脚本的最大运行时间,如果时间到了,本函数会返回错误,单位是秒,默认时间是30秒。

参数:用秒计算的最大运行时间,如果为0,则代表无限时间。

注:采集的话,我们就用无限时间set_time_limit(0);

3、sleep(seconds)

说明:sleep() 函数延迟代码执行若干秒。

参数:必需。以秒计的暂停时间。

 

先给一个基本的测试程序:

//用户关闭浏览器,程序继续运行
ignore_user_abort();
//设定脚本运行无限时间
set_time_limit(0);
//每30秒执行一次 
$interval=30;
do{
	$fp = fopen('text3.txt','a');
	fwrite($fp,'test');
	fclose($fp);
	sleep($interval);
}while(true);

首先运行该程序,然后关闭该页面,程序仍然运行中,test会每隔30秒的填补到text3.txt文件。

最后根据php手册简单介绍一些相关的知识:

1、连接处理

在 PHP 内部,系统维护着连接状态,其状态有三种可能的情况:

0 – NORMAL(正常)
1 – ABORTED(异常退出)
2 – TIMEOUT(超时)

当 PHP 脚本正常地运行 NORMAL 状态时,连接为有效。当远程客户端中断连接时,ABORTED 状态的标记将会被打开。远程客户端连接的中断通常是由用户点击 STOP 按钮导致的。当连接时间超过 PHP 的时限时,TIMEOUT 状态的标记将被打开。

可以决定脚本是否需要在客户端中断连接时退出。有时候让脚本完整地运行会带来很多方便,即使没有远程浏览器接受脚本的输出。默认的情况是当远程客户端连接中断时脚本将会退出。该处理过程可由 php.ini 的 ignore_user_abort 或由 Apache .conf 设置中对应的”php_value ignore_user_abort”以及 ignore_user_abort() 函数来控制。如果没有告诉 PHP 忽略用户的中断,脚本将会被中断,除非通过 register_shutdown_function() 设置了关闭触发函数。通过该关闭触发函数,当远程用户点击 STOP 按钮后,脚本再次尝试输出数据时,PHP 将会检测到连接已被中断,并调用关闭触发函数。

脚本也有可能被内置的脚本计时器中断。默认的超时限制为 30 秒。这个值可以通过设置 php.ini 的 max_execution_time 或 Apache .conf 设置中对应的”php_value max_execution_time”参数或者 set_time_limit() 函数来更改。当计数器超时的时候,脚本将会类似于以上连接中断的情况退出,先前被注册过的关闭触发函数也将在这时被执行。在该关闭触发函数中,可以通过调用 connection_status() 函数来检查超时是否导致关闭触发函数被调用。如果超时导致了关闭触发函数的调用,该函数将返回 2。

需要注意的一点是 ABORTED 和 TIMEOUT 状态可以同时有效。这在告诉 PHP 忽略用户的退出操作时是可能的。PHP 将仍然注意用户已经中断了连接但脚本仍然在运行的情况。如果到了运行的时间限制,脚本将被退出,设置过的关闭触发函数也将被执行。在这时会发现函数 connection_status() 返回 3。

2、相关函数:

  • int ignore_user_abort ( [bool setting] )

Set whether a client disconnect should abort script execution。

Sets whether a client disconnect should cause a script to be aborted.

When running PHP as a command line script, and the script’s tty goes away without the script being terminated then the script will die the next time it tries to write anything, unless value is set to TRUE

  • int connection_aborted ( void )

Check whether client disconnected

  • int connection_status ( void )

Returns connection status bitfield