从零代码爬虫到python函数式编程,不变的竟然是……

Posted 数据团学社

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从零代码爬虫到python函数式编程,不变的竟然是……相关的知识,希望对你有一定的参考价值。

本文约2500字,阅读需要6分钟

关键词:火车采集器  Python   函数式编程


本文为数据分析师(python)微专业学员作品~适合正在学习Python爬虫的朋友,也适合不会编程的朋友学习使用零编程爬虫神器和了解爬虫工作流

p.s.文末有逐行注释的文中示例代码文件分享~


老板最近打算添置一套“豪宅”。为了能够获取海量的房源信息,筛选出最佳选择,老板参加了。在课程老师风趣幽默,深入浅出的讲解之下,掌握了一款名为“火车采集器”的强大工具。今天,特地来向我显摆——


“你知道吗,现在有一款叫火车采集器的软件,很强力的呦,点点鼠标,就能搞到大量数据!你行吗?” 

!!我竟然被老板怀疑技术能力了!今天无论如何都得秀一波! 从零代码爬虫到python函数式编程,不变的竟然是……


下面,让我来彻底揭下火车采集器神秘的面纱,还原其背后的逻辑。


先看老板的需求——

我:“老板,听说你要选购‘豪宅’”。

老板:“那是!不过我要求不高,内环以内,150平米以上就行了。预算嘛...这两年省吃俭用,存了500W。”


得到要求,我先打开某售房网站,以500W以内,150平米以上为基准,筛选出房源:

从零代码爬虫到python函数式编程,不变的竟然是……

还是不少的!当需要采集的数据量比较大的时候,使用爬虫能大大提高工作效率~先看看不用写代码的火车采集器吧——


火车采集器的工作流程


 1、新建任务 


从零代码爬虫到python函数式编程,不变的竟然是……


 2、对特征网址,以页码为变量,设定爬取范围 


从零代码爬虫到python函数式编程,不变的竟然是……


 3、以同样的套路,从一级网址中,获取二级网址


从零代码爬虫到python函数式编程,不变的竟然是……

 

 4、对二级网址中所需获取的数据,根据html标签进行前后截取

 

从零代码爬虫到python函数式编程,不变的竟然是……


从零代码爬虫到python函数式编程,不变的竟然是……

 

 5、运用采集器的模板设置,导出数据的字段和格式 

 

从零代码爬虫到python函数式编程,不变的竟然是……


从零代码爬虫到python函数式编程,不变的竟然是……

 

 6、开始任务,成功爬取数据 


从零代码爬虫到python函数式编程,不变的竟然是……

 

哇!好厉害!看到这里,许多小伙伴都惊呆了,不禁感叹世上竟然有如此神器!

其实非也,支撑起这看似酷炫的操作和吊炸天功能的是一套最基本的爬虫逻辑:

从零代码爬虫到python函数式编程,不变的竟然是……

我们称之为“爬虫工作流”。


程序语言爬取房源信息


既然老板刚学会的火车采集器这么厉害,我当然不能示弱~接下来,学习了火车头的“爬虫工作流”的我,将用Python重新演绎房源信息爬取的全过程(文末有含注释的源代码获取方式~~)


 1、打开代码编辑器,导入四个用于爬虫的库 


import requests
from bs4 import BeautifulSoup
import time
import csv

分别是网页库,爬虫库,时间模块,CSV操作库。这四个库代表了组成一个完整的爬虫工程所需要的四大组件,我把其总结为“4C”模型。 

从零代码爬虫到python函数式编程,不变的竟然是……

Connect:连接组件,用于通过HTTP协议,与站点进行连接。

Crawl:爬虫组件,用于抓取页面中所需要获取的具体信息。

Control:控制组件,用于对工程进行控制,包括工程的进度,效率,异常处理等。

Combine:联合组件,用于整合爬取的信息,做最终的处理。


 2、代码编辑环节 


设计流程化、套路化工作,推荐使用函数式编程

总共两个函数的编程思路如下:



def get_url(start_num,end_num): 
    url_list = [] 
    headers={        'UserAgent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'} 
    url_page = ['https://sh.lianjia.com/ershoufang/pg{}a7ep500/'.format(num) for num in range(start_num,end_num+1)] 
    for page in url_page:
        n+=1 
        print('正在抓取第{}页链接'.format(n)) 
        time.sleep(2) 
        page_data = requests.get(page,headers=headers) 
        soup = BeautifulSoup(page_data.text,'lxml') 
        urls = soup.select('body > div.content > div.leftContent > ul > li > div.info.clear > div.title > a')       
        for u in urls:
            url_list.append(u.get('href')) 
    return url_list


i. 为了模拟真实用户的网页请求,防止被站点反爬,我们先设定一个请求头。这里在游览器中按F12,打开后台,选择Network,然后刷新网页,我们就可以截取到Request Headers信息了。此处,我只添加了User-Agent参数,当然,我们也可以尝试继续添加其他参数,如cookie之类。 


从零代码爬虫到python函数式编程,不变的竟然是……


headers={        'UserAgent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'}


ii. 参照火车采集器的套路,我们需要根据特征网址,构建出所有需要爬取的一级网址。于是,我构造了一个列表解析式。在网址页码部分设置一个等差数列,从而获取到所有网址。这和火车采集器的做法,完全相同。 


url_page = ['https://sh.lianjia.com/ershoufang/pg{}a7ep500/'.format(num) for num in range(start_num,end_num+1)]

iii. 遍历每个一级网址,爬取二级网址。这里使用requests库的get方法访问网页。



从零代码爬虫到python函数式编程,不变的竟然是……

 

page_data = requests.get(page,headers=headers)
        soup = BeautifulSoup(page_data.text,'lxml')  
        urls = soup.select('body > div.content > div.leftContent > ul > li > div.info.clear > div.title > a')


v. 最后,提取url存入列表中,待用。

 

    for u in urls:
       url_list.append(u.get('href'))
return url_list

第一个函数就设计完毕了!看吧,还是挺简单的!

之后,我们进入第二个函数设计。方法类似~


 2.2  建立第二个函数,用于爬取二级页面中所需信息 

 

def craw_inf(url_list): 
    file = open('./lianjia_python.csv','a+',encoding='gbk') 
    writer = csv.writer(file) 
    writer.writerow(['name','price','area_price','area','lng','lat']) 
    inf_all = [] 
    headers={        'UserAgent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'}
    n = 0 
    for url in url_list: 
        n+=1 
        print('正在抓取第{}个房源'.format(n)) 
        time.sleep(3) 
        web = requests.get(url,headers=headers) 
        soup = BeautifulSoup(web.text,'lxml') 
        namel = soup.select('body > div.sellDetailHeader > div > div > div.title > h1') 
        pricel = soup.select('body > div.overview > div.content > div.price > span.total') 
        area_pricel = soup.select('body > div.overview > div.content > div.price > div.text > div.unitPrice > span') 
        areal = soup.select('body > div.overview > div.content > div.houseInfo > div.area > div.mainInfo') 
        lng = soup.get_text().split("resblockPosition:'")[1].split(',')[0] 
        lat = soup.get_text().split("resblockPosition:'")[1].split(',')[1].split("'")[0] 
        for name,price,area_price,area in zip(namel,pricel,area_pricel,areal): 
            data_list = [name.get_text(),price.get_text(),area_price.get_text(),area.get_text(),lng,lat] 
            inf_all.append(data_list)           
            file = open('./lianjia_python.csv','a+',encoding='gbk')
            writer = csv.writer(file)            for row in inf_all:
                writer.writerow(row)
            inf_all = []


i. 首先,我们先创建一个工作表,设置好表头,用于接下来存放爬取的信息。话说,上回我们尝试了pandas对于数据存储的方法,其实,python中处理类似问题的方法有很多,这回我们试着用CSV库去解决这个问题。 


 file = open('./lianjia_python.csv','a+',encoding='gbk') 
    writer = csv.writer(file) 
    writer.writerow(['name','price','area_price','area','lng','lat']) 
    inf_all = []


ii. 然后,重复同样的套路,使用Selector选择器,定位内容。


    for url in url_list: 
        n+=1 
        print('正在抓取第{}个房源'.format(n)) 
        time.sleep(3) 
        web = requests.get(url,headers=headers) 
        soup = BeautifulSoup(web.text,'lxml') 
        namel = soup.select('body > div.sellDetailHeader > div > div > div.title > h1') 
        pricel = soup.select('body > div.overview > div.content > div.price > span.total') 
        area_pricel = soup.select('body > div.overview > div.content > div.price > div.text > div.unitPrice > span') 
        areal = soup.select('body > div.overview > div.content > div.houseInfo > div.area > div.mainInfo')


iii. 这里再提一下经纬度的获取,因为经纬度并不在标签中,而处于页面JS代码部分,我们这里仿照火车采集器的方法,对于文本进行前后截取,同样也能得到想要的结果。 


从零代码爬虫到python函数式编程,不变的竟然是……

 

 lng = soup.get_text().split("resblockPosition:'")[1].split(',')[0] 
 lat = soup.get_text().split("resblockPosition:'")[1].split(',')[1].split("'")[0]


iv. 最后,提取具体内容,写入工作表中。 


    for name,price,area_price,area in zip(namel,pricel,area_pricel,areal): 
            data_list = [name.get_text(),price.get_text(),area_price.get_text(),area.get_text(),lng,lat] 
            inf_all.append(data_list)           
            file = open('./lianjia_python.csv','a+',encoding='gbk')
            writer = csv.writer(file)            for row in inf_all:
                writer.writerow(row)
            inf_all = []


v. 两个函数均编写完毕,我们对函数进行整合


def main():
    url_list = get_url(1,11) 
    craw_inf(url_list)
if __name__ == '__main__':    main()

好了,整个工程设计完成,激动人心的时候终于到了!我怀着虔诚的心情,按下了F5,运行代码!  

从零代码爬虫到python函数式编程,不变的竟然是……

看!是不是和火车采集器很像啊!

哦~~这里再提一句,为了控制爬虫的频率,防着被封IP,我设定了较长的爬虫间隔时间,想要提高效率可以更改time.sleep()中的参数,数字单位为“秒”。 

从零代码爬虫到python函数式编程,不变的竟然是……


经历了为时不多的等待,所有数据均采集完毕了,让我们看看结果!

从零代码爬虫到python函数式编程,不变的竟然是……

 

棒不棒!如果你也想要添置“豪宅”,它将是你不二的选择!(完整代码和注释请看文末福利!)


代码优化和学习建议

对于数据写入部分,最好还是再建立一个函数,待数据采集完成后一次性写入,这样效率更高,更能体现“4C模型”的真谛,但是考虑到爬虫过程中可能发生的意外,从而导致前功尽弃,又不想加入太多代码,这里采取爬一条存一条的策略。


如果采集的数据量比较大,建议使用数据库,运用SQL在数据库中做最后的数据筛选和提取,这能大大提高整理数据的效率和灵活性。像火车采集器,对于采集后的数据,其实先是存入自带的sqllite关系型数据库中的。


CSV库对于Windows系统支持上总会有一点小问题,所以,建议大家使用pandas中的方法对数据进行存储,或者买一台苹果电脑。从零代码爬虫到python函数式编程,不变的竟然是……


结果呈现

数据统统采集下来了,好人做到底,我来给老板先看看,有没有符合要求的房源。我把房源根据经纬度放入地图中,同时,根据上海市中心点,画了一个半径为10公里的圈,大致模拟内环范围。

 

从零代码爬虫到python函数式编程,不变的竟然是……

结果真的是……如此毫无悬念,我一定要把这个振奋人心的结论告诉老板,她一定会高兴的!


老板足足看了一分钟——

“嗯!分析得相当靠谱,鉴于你卓越的工作能力,我决定奖励奖励!”

“好呀好呀!”(我揣摩着老板到底会奖励什么?升职?加薪?共进晚餐?)从零代码爬虫到python函数式编程,不变的竟然是……

“加班!!! ”从零代码爬虫到python函数式编程,不变的竟然是……

从零代码爬虫到python函数式编程,不变的竟然是……

 

 这个故事告诉我们三个道理:

1、面对一些看似牛X的东西,不要畏惧尝试,其实,并没有想象的那么困难,那么高不可攀。学习亦如此。

2、华丽的外表形形色色,背后的套路如出一辙。我们要善于发现事物背后的共同点,形成解决问题的工作流,这样才能事半功倍。

3、生命中有许多可望而不可即的东西,比如,哪怕你拥有500万,也买不起一套“豪宅”,努力工作才是生活的常态。


关注“数据团学社”

并在后台回复【08】

即可免费获取火车采集器安装包和逐行注释的文中示例代码~


了解数据分析师(python)微专业,请点击文末蓝字“阅读原文”~

以上是关于从零代码爬虫到python函数式编程,不变的竟然是……的主要内容,如果未能解决你的问题,请参考以下文章

python为啥叫爬虫

函数式编程(模块基础)

如何把Python入门?

用python写网络爬虫 -从零开始 1 编写第一个网络爬虫

学习《从零开始学Python网络爬虫》PDF+源代码+《精通Scrapy网络爬虫》PDF

智能合约与函数式编程语言(从零开始学区块链 181)