2020年春节学爬虫基础
因疫情的关系,今年春节假期特别长,工作以来未尝有过这样的“待遇”!!无聊之际学习一个完全没有接触过的知识对于本来就是宅男的我也别有一番滋味。于是买了一本《python3 网络爬虫开发实践》跟着做实验。我不知道自己对爬虫/反爬虫的兴致会持续多久!毕竟社会弥漫着浮躁的气氛。不过现在什么都不重要了,健康才是最重要的,毕竟那些因武汉肺炎而牺牲的人们啊,他们在2020年年初肯定有数不完的愿望,可惜他们再也不能实现自己的愿望了,即便是再简单的愿望!世界人民加油!
本文不想列举代码,毕竟书上作者都有公布源码(https://github.com/Python3WebSpider/MaoYan),很简单的代码,自己阅读即可。
但对于没有书的朋友,我打算说两个知识点:
1.利用“Google Chrome”谷歌浏览器阅读请求的html源码,分析电影排行榜在哪里找到
2.正则表达式提取
因为我经常使用SecureCRT和xshell这样的终端工具,而“ctrl+shift+c”快捷键在它们那是复制,在使用谷歌浏览器时我要复制文字有可能会使用“ctrl+shift+c”来复制,导致经常弹出一个html的框,我之前是不知用来干嘛的,现在好了,原来是“网页调试界面”。可以使用“F12”一个按键来触发。
先进入猫眼的电影排行榜网站URL:https://maoyan.com/board/4?offset=0
按下键盘的“F12”进入网页调试界面:
点击“Network”分页下面的“response”标签就能看到猫眼网站回应的html源码了,浏览器就是用这个源码来渲染的,既然我们看到网页上有电影排行,那么该html源码里面肯定包含有这样的信息,我们需要提取出来。我们要点开<body> </body>的内容,发现<dd>节点上确实有我们想要的内容,包括排名、电影片名、主演、上映日期等信息
使用正则表达式即可提取出来:
<dd>.*?board-index.*?>(.*?)</i>.*?name.*?a.*?>(.*?)</a>.*?star.*?>(.*?)</p>.*?releasetime.*?>(.*?)</p>
正则表达式不是python特有的,所以这里不详细说明了。简单说 .*?是使用非贪婪法(如果结果跟我们猜想不一致就要考虑贪婪和非贪婪匹配法)来匹配除了换行符之外的所有字符,而被括号()括住的就是我们要提取的内容,可以使用findall()或者group(n)方法进行获得匹配项,具体参考正则表达式语法和python的re库官方文档。
这只是其中一页,即仅仅包含第一名到第十名的电影名单。我们紧跟着点击“猫眼电影排行榜”底部的“下一页”按钮,再对比一下URL网址的变化,变成了“http://maoyan.com/board/4?offset=10”,可以大胆猜想?后面的“查询条件”中offset=xxx参数跟页数是有10倍关系的,然后就使用归纳法证明,确实如此,第100名肯定在offset=90对应的网址处。
for offset in range(0, 100, 10):
url = 'http://maoyan.com/board/4?offset=' + str(offset)
...
...
大家留意一下网址(URL),一般都是形如:scheme://netloc/path;params?query#fragment,其中scheme代表协议,如https等,netloc为域名,path是访问路径,分号;后面是参数params,问号?后面是查询条件query,一般用于GET请求的URL,而最后的井号#后面跟着fragment锚点,用于直接定位页面内部的下拉位置(但我还没理解这个知识点)。
对了,原书作者用到了yield生成器生成可迭代对象,通过迭代就能将形如[('1', '霸王别姬', '演员',.....),(),()...]的列表中每一项元组('1', '霸王别姬', '演员',.....)的每一项元素转换成字典对象,再将字典保存到txt文本后,人看起来舒服一点。
def parse_one_page(html):
pattern = re.compile('<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name"><a'
+ '.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>'
+ '.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>', re.S)
items = re.findall(pattern, html)
for item in items:
yield {
'index': item[0],
'image': item[1],
'title': item[2],
'actor': item[3].strip()[3:],
'time': item[4].strip()[5:],
'score': item[5] + item[6]
}
...
...
def main(offset):
...
...
for item in parse_one_page(html):
print(item)
...
...
我没有提取那么多信息只是爬了排名、电影名、主演以及上映时间这4项而已,所以我选择了简单做法:
def parse_one_page(result, html):
pattern = re.compile(
'<dd>.*?board-index.*?>(.*?)</i>.*?name.*?a.*?>(.*?)</a>.*?star.*?>(.*?)</p>.*?releasetime.*?>(.*?)</p>',
re.S
)
items = re.findall(pattern, html)
with open(result, 'a', encoding='utf-8') as f:
for item in items:
f.write(item[0]+"\n" + "<<" + item[1] + ">>\n" + item[2].strip() + "\n" +
item[3].strip() + "\n" + "\n\n")
最后,我列举出部分爬到的电影榜,大家可以下载来看,有些电影确实好看,在春节武汉肺炎期间我也看了不少开心电影,如没排上名的粤语版《开心鬼系列》、《老豆唔怕多》等:
1
<<霸王别姬>>
主演:张国荣,张丰毅,巩俐
上映时间:1993-07-26
2
<<肖申克的救赎>>
主演:蒂姆·罗宾斯,摩根·弗里曼,鲍勃·冈顿
上映时间:1994-09-10(加拿大)
3
<<这个杀手不太冷>>
主演:让·雷诺,加里·奥德曼,娜塔莉·波特曼
上映时间:1994-09-14(法国)
4
<<罗马假日>>
主演:格利高里·派克,奥黛丽·赫本,埃迪·艾伯特
上映时间:1953-08-20(意大利)
5
<<泰坦尼克号>>
主演:莱昂纳多·迪卡普里奥,凯特·温丝莱特,比利·赞恩
上映时间:1998-04-03
6
<<唐伯虎点秋香>>
主演:周星驰,巩俐,郑佩佩
上映时间:1993-07-01(中国香港)
虽然HTML和爬虫以前没有接触过,但发现编写爬虫的过程是跟“软件调试或****”的思路相似,都是要“大胆猜想,细心求证”,我以前确实有想过做一些****、灰帽子之类的实验,后来没有了这个原动力,可能是浮躁的心驱使的吧!现在总算蜻蜓点水了,还是那句话,不忘初心,无论做什么事,坚持很重要!譬如,能坚持跑步锻炼的话就是不错的事情,抵抗力强了,还自信了!