以函数式编程的方式设计最简单的网络爬虫!
大家也许好奇什么是函数,与我们数学中的函数有什么区别呢?今天我们从函数的定义、用法、实战三个方面分享函数式编程的思想。这一版又有改进,丢弃了很多图片,以原版代码的形式给大家分享,方便大家复制粘贴程序。如果大家有任何疑问
学习Python中有不明白推荐加入交流群
号:960410445
群里有志同道合的小伙伴,互帮互助,
群里有不错的视频学习教程和PDF!
主要内容分为三个部分:
1、函数的定义;
2、函数的用方法;
3、设计初级的网络爬虫。
§§Python函数的定义
一、python的函数定义:
在数学中函数表示的未知量x通过一种运算f映射到f(x)的一种关系,即{x --->f--->f(x)}, 但是在计算机编程语言中函数仅是为实现某一具体功能的代码模块的统称****。比如,上节我们分享的模拟网站登陆的函数,仅仅实现登陆的功能。我们从以下几个方面开始拆分python编程语言中函数。
(1)如何用代码定义函数;
(2)函数里都包含那些内容;
(3)函数怎么用(专业的说法是:函数怎么调用)。
1、如何用代码定义函数:
用def+ 一个空格 + 函数名+英文的括号或者参数+英文的冒号。
无参数函数的代码示例:
def hello():
print("hello, Cly!")</pre>
这样就定义了一个最简单的函数,是不是很简单呢!。
有参数函数的代码示例:
def hello(name):
print("hello ",name)
</pre>
2、函数里都包含那些内容:
(1)函数里的内容包括:循环、判断或者引用第三方库的一些功能。上图中函数里面只有一行代码,以最简单的例子让大家知道怎么定义函数。如下图中login函数里的内容、read_data_from_txt函数里的内容。
代码示例:
image.png
image.png
说的直白点:函数就是编写一系列的逻辑来处理数据的具体方法。比如上图中:login负责登陆、read_data_from_txt负责读取文件中的数据。3、函数怎么用:
(1)对于无参数的函数调用:
函数名+英文括号()
**def hello():
print("hello, Cly!")
函数调用 hello()**</pre>
输出结果:
hello, Cly!
</pre>
(2)对于有参数的函数调用:
函数名+英文括号(参数)
<**def hello(name):
print("hello",name)
函数调用和传参 name = 'Cly' hello(name)**</pre>
输出结果:
hello, Cly!</pre>
注意的是:函数的参数不一定只有一个,有可能要传入多个参数,这就要结合实际情况的需要来定义了。参数的类型有可能是:字符串、列表、字典、文件等。
§§Python函数的用法
二、函数的用方法:
用法说明:
(1)减少程序中代码的重复、增加程序的易读性;
(2)封装一些功能,方便工程的管理;
1、减少程序中重复的代码、增加程序的易读性:
如代码块1中:save_data函数中重复出现两次 打开文件写入文件的操作。 为了使代码更简洁、易于理解,完全可以把打开文件写入文件封装到一个函数中,这样代码就更简洁了,如代码块2所示。
代码块1:
def**save_data(datas):
'''把处理好的数据存入文件中'''
if len(datas) != 0:** with open("SaveDataToFile.txt", "w+") as f:
f.write(datas)
print("******数据保存完毕******") else: with open("SaveDataToFile.txt", "w+") as f:** warning = u'数据为空,请检查参数的处理工程! ' ** f.write(warning) print(warning)
代码块2:
def**write_data_to_file(data, file_name):
'''把数据写入文件'''
file_name = file_name + ".txt"
with open(file_name, "w+") as f:****# 打开文件 ** f.write(data) # 数据写入文件
**def**** save_data(data):
'''把处理好的数据存入文件中'''
file_name = 'SaveDataToFile'
if len(data) != 0:
write_data_to_file(data, file_name) # 函数调用,把数据存入文件中
print("******数据保存完毕******")
else:
warning= u'数据为空,请检查参数的处理工程! '
write_data_to_file(warning, file_name) # 函数调用,把异常情况保存到文件中
print(warning)**
</pre>
2、封装一些功能,方便工程的管理:
如上述 代码块2 中,把打开与保存文件的过程封装到函数
write_data_to_file(data, filename)中。传入要保存到文件里的数据:
data与文件名:filename。这样做的好处,每次不用在函数体中修改文件名与数据,只需把这两个变量当成参数传递给write_data_to_file函数即可,方便管理与以后的调用。
§§利用函数设计初级的网络爬虫
三、设计初级的网络爬虫:
下面就以纯函数的形式编写一个最简单的定向网站爬虫程序----爬取以比特币为代表的数字货币的市值等信息。
运行此程序前,你需要安装python的三个第三方包:
1,requests库:爬取网站信息的主要库之一。
**安装方法: pip install requests**
2、pandas库:python数据分析的主要库之一。
**安装方法: pip install pandas**
3、beautifulsoup库:一个很好用的网页信息提取的库。
**安装方法: pip install beautifulsoup4**
代码示例:
< # -- coding:utf-8 -- import requests import**** pandas ****as****pdimport****time from**** bs4 ****import****BeautifulSoup from**** requests.exceptions ****import****RequestException
def send_request(url):
'''通过 requests.get(url=url)获取网页源码'''
# 捕获异常 try:****# 以get的方式获取网页源码 ****
response = requests.get(url=url, timeout=10)
# 判断网站是否有相应,有的话就会返回200的状态码。
if response.status_code == 200:
text = response.text
return BeautifulSoup(text, 'lxml')
except RequestException as e:
print("打开页面错误:" % e)
return None
</pre>
def**get_detial_url(total_page_number):
"""本函数功能:构造最终要爬取的所有URL连接"""****# 构造爬虫要爬取的目标链接地址** **start_urls = ['https://www.feixiaohao.com/list_{}.html'.format(i) for i in range(1, total_page_number + 1)]
detail_url_str = '****https://www.feixiaohao.com/currencies/{}/'**
**coin_ids = []
通过上面的send_request(url)函数获取源码后解析要构造的链接。
for url in start_urls:
coin_ids += [row.attrs['id'] for row in send_request(url).select('#table tr')[1:]]
detail_urls = (detail_url_str.format(c_id) for c_id in coin_ids)
返回最终的连接地址
return detail_urls**
def**download_webpage_info(page_num, file_name='排名前5百的币.csv'):
"""获取最终信息,保存至csv文件中"""
# 初始化数字货币的市值,为存值做准备
pv = []
# 初始化数字货币的其他信息,为村制做准备。
detail_info = []
print("********************* 正在非小号爬取数据......************************")
i = 1
for url in get_detial_url(page_num):
print("[%s]" % i, url)
# 获得流通市值
pv.append([str(row.string[2:]).strip()** **for** **row in send_request(url).select('.firstPart .cell .sub')[1]])
# 获得类为scondPark的li标签的信息value类
detail_info.append([str(row.text).strip() for row in send_request(url).select('.secondPark li .value')[:4]])
i += 1
# 报数据保存到CSV文件中。
df1 = pd.DataFrame(data=pv, columns=[u'流通市值($)']) # pandas的DataFrame数据类型声明。
df2 = pd.DataFrame(data=detail_info, columns=[u'英文名', u'中文名', u'上架交易所', u'发行时间'])
df = pd.concat([df2, df1], axis=1)writer = pd.ExcelWriter(filename)
df.to_excel(writer, index=False)
writer.save()
print("数据爬取完毕")**
**if**** name == ' main ':
# 程序执行的入口
n = int(input("请输入你要爬取的页面数量(备注:非小号共有23页、每页100个币)::"))
download_webpage_info(n, filename=u'流通市值.xlsx')**
注:****此程序完全可以执行,大家可以复制粘贴,查看运行结果。
四、大总结:
(1)函数的其实就是程序一个一个的功能模块****。
(2) 函数封装一定的逻辑与方法,简化重复代码、便于管理和维护。
(3)特别注意一个函数最好只执行一个功能,如果一个函数中有多个功能,尽量拆分成两个或者更多的函数****。