闲来无事,想要学习一下 Python,十月初的时候搭好了 ubuntu 的环境,用的是 Ubuntu 16.04 32 位 + sublime Text3,轻量级的编程环境,感觉用起来还是比较舒服的。也陆陆续续地学习了一下 python 的语法和相关的知识点,并没有感觉到 python 有什么特别的地方,数据结构中的列表,元组和字典,还没有感到其特点在哪里比较明显,只是一个数据结构而已。恰好学院老师让搜集就业相关信息,所以就想尝试去先写一个爬虫,爬一下相关网站的相关链接。先提起兴趣,再去学习枯燥的知识点。
当然,和教程还是有一点不一样的,教程中是先定位了模块的 id,但是我们学校的就业信息网列表那里并没有模块的 id,所以尝试直接取获取链接文本所在模块的信息。获取得到的内容除了我想要的东西意外还有奇奇怪怪的东西,后来查了一下模块的 id 是唯一的,但是模块下的子名字是可以重复的,因为获取的是列表,并且信息的格式基本上是固定的,所以直接获取列表的一个子表就可以了,当然 =,= 不懂 html 的我是不了解具体原因的。。
这样就是静态的抓取了一个网页里面的部分文章标题及链接,但是想实现的是提醒更新的功能。很自然地一个想法就是拿爬下来的内容和之前的内容进行比较,没有更新的就直接忽略,有更新的话就把更新内容保存下来,最后只提醒更新内容就好了。正好 python 处理字符串还是比较人性化的,文件操作里面有 f.readline(),同时可以直接进行字符串的比较,所以就拿爬下来的第一行数据和之前文件里的第一行数据进行比较,如果相同的话忽略本次爬取,不同的话循环比较,直到遇到相同的数据,把之前的数据存到本地,实现更新内容的动态提醒。最终实现了对三个网页,山东大学(威海)就业信息网的两个模块和哈尔滨工业大学(威海)的一个模块的数据提取。代码如下:
View Code
- 1#coding = utf - 8 2#@author: blueprintf 3#@E - mail: blueprintf@gmail.com 4#@version: 10 / 28 5 import requests 6 import sys 7 from pyquery import PyQuery as pq 8 reload(sys) 9 sys.setdefaultencoding('utf-8') 10 11#output file init 12 fadd = '/home/myc/Documents/pythonPro/update.txt'13 f = open(fadd, 'w+') 14 f.truncate() 15 f.close() 16 17#sduwh campus recruitment 18 url = 'http://job.wh.sdu.edu.cn/item/79_1.html'19 r = requests.get(url) 20 p = pq(r.text).find('td>a') 21 length = len(p) 22 p = p[1 : length - 6] 23 check = pq(p[0]).text() + '\n'24 fadd = '/home/myc/Documents/pythonPro/wh.txt'25 f = open(fadd, 'r+') 26 exist = f.readline() 27 f.close() 28
- if exist != check: 29 print 'sduwh campus recruitment update'30 seq = ''31
- for d in p: 32 tmp = pq(d).text() + '\n'33
- if tmp == exist: 34
- break 35 seq += pq(d).text() + '\n' + 'http://job.wh.sdu.edu.cn/' + \36 pq(d).attr('href') + '\n'37 38 fadd = '/home/myc/Documents/pythonPro/wh.txt'39 f = open(fadd, 'w') 40 f.write(seq) 41 f.close() 42 fadd = '/home/myc/Documents/pythonPro/update.txt'43 f = open(fadd, 'a') 44 f.write(seq) 45 f.close() 46 47#sduwh employ information 48 url = 'http://job.wh.sdu.edu.cn/item/80_1.html'49 r = requests.get(url) 50 p = pq(r.text).find('td>a') 51 length = len(p) 52 p = p[0 : length - 6] 53 check = pq(p[0]).text() + '\n'54 fadd = '/home/myc/Documents/pythonPro/whzp.txt'55 f = open(fadd, 'r+') 56 exist = f.readline() 57 f.close() 58
- if exist != check: 59 print 'sduwh employ information update'60 seq = ''61
- for d in p: 62 tmp = pq(d).text() + '\n'63
- if tmp == exist: 64
- break 65 seq += pq(d).text() + '\n' + 'http://job.wh.sdu.edu.cn/' + \66 pq(d).attr('href') + '\n'67 fadd = '/home/myc/Documents/pythonPro/whzp.txt'68 f = open(fadd, 'w') 69 f.write(seq) 70 f.close() 71 fadd = '/home/myc/Documents/pythonPro/update.txt'72 f = open(fadd, 'a') 73 f.write(seq) 74 f.close() 75 76#hitwh employ information 77 url = 'http://job.hitwh.edu.cn/showmore.php?actiontype=5'78 r = requests.get(url) 79 r.encoding = 'gbk'80 p = pq(r.text).find('#p2_c td>a') 81 length = len(p) 82 p = p[3 : length] 83 check = pq(p[0]).text() + '\n'84 fadd = '/home/myc/Documents/pythonPro/hitwh.txt'85 f = open(fadd, 'r+') 86 exist = f.readline() 87 f.close() 88
- if exist != check: 89 print 'hitwh employ information update'90 seq = ''91
- for d in p: 92 tmp = pq(d).text() + '\n'93
- if tmp == exist: 94
- break 95 seq += pq(d).text() + '\n' + 'http://job.hitwh.edu.cn/' + \96 pq(d).attr('href') + '\n'97 fadd = '/home/myc/Documents/pythonPro/hitwh.txt'98 f = open(fadd, 'w') 99 f.write(seq) 100 f.close() 101 fadd = '/home/myc/Documents/pythonPro/update.txt'102 f = open(fadd, 'a') 103 f.write(seq) 104 f.close()
因为对 python 语言不太熟悉,所以可能很多语法的写法并不像 python 工程师的写法,之后会系统地学习然后改过。
到这里还算比较顺利的,代码量不大,直接调库就实现了我想要的功能,一共用了三四个小时的样子,但是这样明显不能够满足我的需求,毕竟 python 是一个脚本文件,如果我想把它发给别人,那对方也必须要配置好 python 环境才可以运行。很自然的一个想法就是想把脚本文件转化成可执行文件(噩梦从此开始)。
从网上查了一下,还真有实现这个功能的软件,也是一个脚本文件的样子,最常用的有两个:py2exe 和 pyinstaller,都是针对 python2 的。一开始尝试在 ubuntu 下进行文件转换,但是没有成功,猜想是因为在 ubuntu 下没有 exe 这样的文件格式(有成功在 ubuntu 下转换的欢迎交流)。然后在 windows 下因为我的电脑之前装的是 python3.5,尝试卸载重新装 2.7.x 的时候环境可能出了点问题,不能实现 pip 功能,cmd 下载速度也奇慢无比,遂借了舍友的电脑从安装 python 开始做起(若干个小时过去了)。。。。
然后下载了 py2exe 和 pyinstaller,分别进行了尝试。py2exe 需要先自己写一个 setup.py,写了个简单的但是报错缺少模块儿,尝试加失败,放弃。pyinstaller 比较傻瓜,告诉他需要转成什么样的文件他就会帮你转,所以选择了这个。因为代码中用到了 pyquery 和 requests 两个包,所以就先下载这两个包,下载过程中 pip 报错,libxml2 not installed,下载了 libxml2-python-2.7.7.win32-py2.7.exe,安装以后在 Lib 里面找到了 libxml2,但是还是报错。。百度了好久也没有解决这个问题,有的说要先安装 lxml,但是在安装高版本 lxml 的时候也会报这个错误。。所以就先安装了一个低版本的 lxml,把 pyquery 包先装上了。
然后尝试使用 pyinstaller 进行编译,编译很顺利,但是编译完之后直接闪退。查了很久,也查了 pyinstaller 相关的介绍说明,看见 Build 文件夹下面有一个 warn*.txt 文件,里面 missing 了各种模块,于是开始一个一个安装模块,但是并没有什么卵用,绝望 =,=。快睡觉的时候才想起来自己的老本行,能不能 debug 一下,发现虽然还是会闪退,但是可以确定是在 import pyquery 的时候闪退的。这时候感觉 lxml 是肯定必须要升级的了,后来从网上找了一个 lxml 的安装文件,安装过程中没有报错,安装了以后竟然真的可以运行了,感动。
但这个感动还是早了点,运行以后发现每次更新都会把所有数据全部输出一遍,而不是更新的那部分。后来才明白,windows 下面和 ubuntu 下面的编码机制是不一样的。。OMG,给跪了,在 ubuntu 中,换行符是'\n',而在 windows 下,换行符是'\r\n',在编解码方面也有一定的差别, 可以。一开始还想要 print 一下看看差别,后来一直在报解码错误,真的是蜜汁错误,用的 utf-8 编码,结果报 GBK 的错误。后来发现有 repr 函数可以直接显示编码的内容,干脆就直接比较编码了,发现 windows 的 utf-8 编码在开始的时候会有一个 u'\feff',猜可能是 utf 的编码标识符,所以用 gbk 去读的时候会错位读不出换行符?改完以后终于可以运行了,感动天感动滴。。
还有一个点需要注意一下,在用 pyinstaller 进行转换的时候,可能会有关联文件,比如说调用了某个数据文件之类的,这个时候可以在生成的 spec 文件 data 那里就行修改,加上数据文件的路径。当然程序生成的文件是不需要加在里面的。
最后。。两天时间做出来的程序的结果,这个必须要贴图了,还是比较满意的,之后可以加入其他的网页链接,继续丰富这个小程序。感觉爬虫做起来还是比较好玩的,但是工程性要强很多。
------------------------------------------------- 我是分界线 --------------------------------------------------
感想:
1,以前觉得 python 是个很高级的语言,会的人应该非常厉害,但是自己去做的时候才发现所谓高级语言是因为集成的好,只要会调用就可以实现想要的功能,难点反而是在于能不能把想法转化成简洁,高效的程序。
2,爬虫这种东西,真的是很可怕,可以大大提高人的工作效率,但也是个双刃剑,后来体会了一下爬虫爬去 baidu 搜索的相关信息,真的是和人肉搜索一样的感觉,所以在网上的信息尽量不要用真名和易于检索的资料。当然,那些大公司手里面的数据真的会很恐怖。
3,工程性的东西真的真的真的好繁琐!
来源: http://www.cnblogs.com/blueprintf/p/6013432.html