上两篇讲完了模拟登录和验证码识别,于是这篇到了爬虫最核心的部分:爬取数据。前面的一切都只是为了爬取数据罢了,爬取数据也是爬虫最核心的部分。
为什么这篇又是隔了很久才发?嗯,原因和之前说的一样,因为我懒……
其实也不全是因为懒…自学python后,发现如果想当一个合格的码农,只会那么一两种语言是不可能的,现在的时代就是这样。python–>数据库–>算法–>web开发–>前端三件套(HTML、CSS、JS)–>UI、交互–>后端(PHP、java)–>通信协议–>计算机结构–>liunx……
看到一个问题、解决问题、造轮子、学新东西…造轮子这个行为会不断促使我去学新的东西,学的东西越多,造的轮子也越好用越好看,虽然现在这个时代,有无数的轮子可以直接拿来用,其中的许多也远比我自己要造得好,但我还是喜欢自己造轮子。
所以我似乎进到了一个深坑里面,不过这个坑应该比化学的坑要浅,所以我就打算呆在里面了…
所以我报了学校的一位老师开的一个java培训班,目前来讲,在这里我学到最多的不是java本身(毕竟各种语言的语法部分其实都差不多,培训班前期也只能慢速的教语法),而是系统的编程思想,上课我想的最多的不是这里java怎样怎样,而是这里python会怎样怎样。关于这个,我要再抽时间水一篇博客(虽然根本没人看)
。
所以说我为什么写东西这么慢呢?除了懒以外(我绝对没有否认自己懒),主要还是因为上java培训班需要大量的时间,同时java培训班导致沉迷(并没有)于ACM,因为java培训班那边要求做ACM题来熟悉java。
有一句说一句,我还是更喜欢PAT,网页设计友好、支持的语言种类极多、入门题目的难度比ACM高,这一切都是极好的。反正我也不会参加比赛,PAT足以满足熟悉某种语言的需求,当然PAT的缺点就是套路太死、题太少,不过对于练手完全足够。
其实并没有什么思路,如果已经获取到html页面了的话,有一堆方法可以拿到数据,页面规范的情况下,正则表达式都行,前提是正则表达式玩的很溜。
我用的是python3自带MyHTMLParser类,靠着这个类即可做简单的html解析。
如果碰到结构非常复杂的html页面,MyHTMLParser会绕的很头大,但也还算能做。至于那些靠JS加载的页面(事实上很多页面都是这样)…MyHTMLParser无能为力,但有别的东西能做,我在知乎上看到过一堆,但我自己完全没去学习过,所以这里就不BB自己不了解的东西了,反正迟早有一天要用上的,到时候再来水博客。
MyHTMLParser类的基本结构长这样(这段代码是直接从廖雪峰dalao的个人网站复制过来的,如果你有兴趣学习python,那里是极好的地方,蛤乎上有人称那里是国内最好的python中文在线学习网站,事实上我也觉得确实如此。)
from html.parser import HTMLParser
from html.entities import name2codepoint
class MyHTMLParser(HTMLParser):
def handle_starttag(self, tag, attrs):
print('<%s>' % tag)
def handle_endtag(self, tag):
print('%s>' % tag)
def handle_startendtag(self, tag, attrs):
print('<%s/>' % tag)
def handle_data(self, data):
print(data)
def handle_comment(self, data):
print('')
def handle_entityref(self, name):
print('&%s;' % name)
def handle_charref(self, name):
print('%s;' % name)
parser = MyHTMLParser()
parser.feed("html文件或文件流")
一开始看到这段东西的时候我没弄懂MyHTMLParser类到底是怎么工作的,直到后来才搞明白。
比如看下面这一段MyHTMLParser类的代码。
from html.parser import HTMLParser
from html.entities import name2codepoint
class MyHTMLParser(HTMLParser):
def __init__(self):
HTMLParser.__init__(self)#继承父类
self.tag = 0
def handle_starttag(self, tag, attrs):
if tag == "h1":
self.tag = 1
def handle_data(self, data):
if self.tag == 1:
print(data)
self.tag == 0
这段代码的作用是提取出某html文件内所有的标题,工作方式是这样:handle_starttag方法负责检测每个标签,当handle_starttag检测到html的某个标签的值为“h1”时,将tag的值变成1。而handle_data方法负责获开始与结束标签之间的数据,且当tag=1时,输出当前的数据,即标题内容,最后再令tag=0.
虽然这段代码写的很蠢…但基本上 MyHTMLParser模块的工作方式就是这样。靠着handle_starttag、handle_endtag、handle_startendtag、handle_data、handle_comment、handle_entityref、handle_charref之间的互相配合,来获取html的数据,同时MyHTMLParser作为一个类,也支持直接添加其他的方法进去,如果是java似乎是需要改动源码才行。
不过这种方式也导致MyHTMLParser模块对非常复杂的html或者是瞎B写的html的解析会非常的麻烦。
关于我爬教务处的具体代码就不上了,里面会泄露的信息太多。
数据储存我并没有用到数据库,主要还是因为我不会,当时是直接存进excel文档中的,用的是别人造好了的现成轮子,除去导包外就只有2行代码:with方法开文档,写入。然后就没了,所以也就略过不上了…
(这里透露出一个细节,我每写入一行数据就需要打开、关闭一次文档,这很蠢,效率很低,实际操作中这么写简直智障,只是我当初懒得写错误处理,为了报错中止时保证不丢数据,就这么写了,教务处的渣服务器会各种花式报错,一个一个写处理方式太麻烦了。)
python操作excel的第三方包有很多,自行搜索学习就是。
由于这部分全是用的现成的轮子…实在是写不出什么总结…
期望某一天我能够开始给别人造轮子吧。