聚沙成塔--爬虫系列(五)(请做个「优雅」的人)

2017-10-18

苏菲?玛索

版权声明:本文为作者原创文章,可以随意转载,但必须在明确位置表明出处!!!

通过上一篇文章聚沙成塔–爬虫系列(四)(爬取糗事百科段子)我们已经基本了解了爬虫的思想,首先是通过urlopen(…)函数去请求页面,然后通过正则表达式从函数返回回来的页面元素去匹配我们需要的信息,上一篇文章我们已经实现了从「糗事百科」爬取搞笑段子。

但是我们没有去考虑过编码规范,写法。随着需求越来越多我们的代码肯定会不断的增加,难道我们就这样从头写到尾吗?如果你的代码成千上万行了,到那时对你来说将会是一种灾难,代码会变得连你自己都不想去看一眼,生活中我们要做一个「优雅」的人,这样才会有人去欣赏你。编码一样,在编码中我们更要做一个「优雅」的人,让阅读你代码的人赏心悦目,让你的代码变得高可复用。不管在生活中还是工作中,请让自己做一个「优雅」的人。

函数的意义

在基础语法的一章聚沙成塔–爬虫系列(二)(python3基础语法)我们已经提到过函数,在这一章我们主要讲一讲函数的用法。让我们的代码变得像积木一样(可拼接),或者更通俗一点像“活字印刷术”一样

活字印刷

函数的设计

既然函数的作用是模块化,那么函数的设计就需要一定的要求了,从我个人的工作经验中,我一般设计函数通过参考一下几点:

  • 通用性: 何谓通用性呢,就是你设计的函数不仅你自己能用,别人也能用,这个在多人开发中经常会涉及到,这类函数一般是公共函数,或者工具类函数,比如时间格式的转化、文件读写的操作、文件的备份、移动等等。
  • 独立性: 你设计的函数只需要在你自己的工程中使用,这个时候你的函数参数可以是自己设计的对象。
  • 功能性: 函数的设计尽量以功能性为主,比如我们可以将上一篇文章的读取页面设计为一个函数,匹配规则设计为一个函数。

设计师

从现在开始让我们做个「优雅」的人


上一篇文章我们的代码写得并不「优雅」,如何让我们的代码变得更优雅一些呢。我们需要将代码封装成几个函数模块,让代码的可读性更高,可复用性更强。那我们的函数要怎么设计呢,下面是我用函数改写后的结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import urllib
from urllib import request
import re
url = 'https://www.qiushibaike.com'
user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'
headers = {'User-Agent': user_agent}
def read_html(url, headers, codec):
'''[read_html]
[读取html页面内容]
Arguments:
url {[string]} -- [url地址]
headers {[dict]} -- [用户代理,这里是一个字典类型]
codec {[string]} -- [编码方式]
Returns:
[string] -- [页面内容]
'''
# 构建一个请求对象
req = request.Request(url, headers=headers)
# 打开一个请求
response = request.urlopen(req)
# 读取服务器返回的页面数据内容
content = response.read().decode(codec)
return content
def match_element(content, pattern):
'''[match_element]
[匹配元素]
Arguments:
content {[string]} -- [文本内容]
pattern {[object]} -- [匹配模式]
Returns:
[list] -- [匹配到的元素]
'''
# 匹配所有用户信息
userinfos = re.findall(pattern, content)
return userinfos
content = read_html(url, headers, 'utf-8')
pattern = re.compile(r'<div class="article block untagged mb15[\s\S]*?class="stats-vote".*?</div>', re.S)
userinfos = match_element(content, pattern)
if userinfos:
pattern = re.compile(r'<a href="(.*?)".*?<h2>(.*?)</h2>.*?<div class="content">(.*?)</div>', re.S)
for userinfo in userinfos:
item = match_element(userinfo, pattern)
#print(item)
if item:
userid, name, content = item[0]
# 去掉换行符,<span></span>,<br/>符号
userid = re.sub(r'\n|<span>|</span>|<br/>', '', userid)
name = re.sub(r'\n|<span>|</span>|<br/>', '', name)
content = re.sub(r'\n|<span>|</span>|<br/>', '', content)
print((userid, name, content))

这样改写后的结果是不是要比没改写之前可读性好,可复用性更高了,首先read_html(…)函数保证了如果我们要读其它url网页内容,是不是只需要给函数传递相应的值就可以了。没改写之前若是我们又要去读取一个网页内容,唯一的做法就是再去重复的写一遍。march_element函数也是同样的道理。

当然这样的写法对代码的可读性和可维护性不是最好的,后面我们介绍到类的使用的时候将会再次重写它,期待你的持续关注,最后奉上运行结果。

结果.png


欢迎关注我的公众号:「爱做饭的老谢」,老谢一直在努力…

上一篇:聚沙成塔–爬虫系列(四)(爬取糗事百科段子)
下一篇:聚沙成塔–爬虫系列(六)(聚沙成塔–爬虫系列(六)(请做个内外兼修的高手))