什么是爬虫?实践源于理论。在制作爬虫之前,首先要了解相关的规则和原理。您必须知道,互联网不是法外之地。爬虫你可能哪天都不会操作...首先,我们来看看爬虫的定义:网络爬虫(又称网络蜘蛛、网络机器人,在FOAF中更常被称为网络追赶者community)是一种按照一定规则自动抓取万维网上信息的程序或脚本。总之,它是一个在线信息搬运工。让我们来看看爬虫应该遵循的规则:robots协议是一个存储在网站根目录下的ASCII编码的文本文件,它通常告诉网络搜索引擎机器人(也称为网络蜘蛛)这个网站有哪些内容什么不应该被搜索引擎的机器人获取,哪些可以被搜索引擎的机器人获取。一句话告诉你哪些东西可以爬,哪些东西不能爬。了解了定义和规则之后,最后就是熟悉爬虫的基本原理了。这很简单。作为一个灵魂画师,我画个示意图给大家看下。(⊙o⊙)……尴尬,为什么鼠标写的那么难看,我都不好意思说我是学过书法的,好尴尬。项目背景的理论部分基本讲完了。可能有小朋友觉得我啰嗦,废话不多说,直接说实际的部分。本爬虫小项目是应朋友的需求,从中国木材价格指数网爬取红木价格数据,方便红木研究报告的撰写。该网站看起来像这样:必填字段已用红色框标记。粗略看了一下数据量,1751页就有5万多条记录。如果你尝试复制粘贴,你不知道你会坚持到猴年。而python只需要运行几分钟就可以把你excel中的数据全部保存下来,是不是很舒服?\项目实战工具:PyCharmPython版本:Python3.7浏览器:Chrome(推荐)第一次写爬虫的朋友可能会觉得很麻烦。爬取一个页面首先我们要简单分析一下网页的结构,右击勾选,然后点击Network,刷新网页,继续点击Name列表中的第一个。我们发现该网站的请求方式为GET,请求的header中反映了用户的电脑系统、浏览器版本等信息。接下来用pip安装并导入爬虫需要的所有库。所有库的功能都有注释。importcsv#用于将爬取的数据存储为csv格式,可以直接用excel打开importtime#用于延迟请求,爬取速度太快容易从时间倒过来importsleep#同上importrandom#使用延时设置随机数,尽量模拟人的行为importrequests#用于向网站发送请求fromlxmlimportetree#lxml是第三方网页解析库,功能强大快速构建请求url,添加header信息headers复制上面标记的User-Agent通过requests.get方法向服务器发送请求并返回html文本。加header的目的是告诉服务器你是真人在访问它的网站。如果你不加header直接访问服务器,在python访问的其他服务器上就会显示,那你很可能被反爬了,常见的反爬就是封你的ip。url='http://yz.yuzhuprice.com:8003/findPriceByName.jspx?page.curPage=1&priceName=%E7%BA%A2%E6%9C%A8%E7%B1%BB'headers={'用户-Agent':"Mozilla/5.0(Macintosh;IntelMacOSX10_14_6)AppleWebKit/537.36(KHTML,likeGecko)Chrome/81.0.4044.129Safari/537.36",}response=requests.get(url,headers=headers,timeout=10)html=response.textprint(html)下面我们运行一下上面的代码,看看效果:看到这里,刚接触爬虫的朋友可能有点懵。其实这就是网页的源代码。我们右键打开源码看看。看起来是这样的:我们需要提取的数据隐藏在这个网页的源代码中,我们需要使用lxml库中的etree方法来解析网页。parse=etree.HTML(html)#解析完网页后,我们就可以愉快的提取出我们需要的数据了。方法很多,xpath,select,美汤,还有最难的re(正则表达式)。本文爬取的数据结构比较简单,直接玩xpath吧。我们在源码中发现每一行数据都对应一个id=173200的tr,所以先把这些tr提取出来。all_tr=parse.xpath('//*[@id="173200"]')有些朋友不会写xpath。然后找个简单的方法,直接把需要的xpath复制过来。tr都已经提取出来了,接下来还得依次从tr中提取具体的字段。例如,提取产品名称字段,单击第一个tr,选择产品,并复制其xpath。这同样适用于其他领域。需要注意以下几点,tr={key1:value1,key2:value2}是python字典数据类型(也可以根据自己的兴趣或需要保存为列表或元组类型)。''.join是指将得到的列表转换成字符串。./是指继承前面的//*[@id="173200"],strip()是指对提取出来的数据进行简单的格式清洗。对于trinall_tr:tr={'name':''.join(tr.xpath('./td[1]/text()')).strip(),'price':''.join(tr.xpath('./td[2]/text()')).strip(),'unit':''.join(tr.xpath('./td[3]/text()')).strip(),'supermaket':''.join(tr.xpath('./td[4]/text()')).strip(),'time':''.join(tr.xpath('./td[5]/text()')).strip()}我们打印print(tr)看看效果。此时,你的心情可能是这样的:不过还没完呢,数据有了,我们要把csv格式保存到本地,这一步比较简单,直接贴代码即可。withopen('wood.csv','a',encoding='utf_8_sig',newline='')asfp:#'a'是附加模式(加法)#utf_8_sig格式导出没有乱码的csvfieldnames=['name','price','unit','supermaket','time']writer=csv.DictWriter(fp,fieldnames)writer.writerow(tr)打开新生成的wood.csv,看起来是这样的:两次爬取多个pages别高兴得太早,你才爬了一页数据,人家复制粘贴的速度比你快。我们的志向不在这里,而在诗和远方,哦不,是秒爬海量数据。那么,我们如何爬取多页数据呢?没错,就是for循环。我们回过头来分析一下url:http://yz.yuzhuprice.com:8003...我们试着把里面的page.curPage改成2,如下:或许你会发现其中的奥秘,只要把page.curPage改一下就可以实现翻页。OK,那我们就在url前面加个循环就行了。format(x)是一个格式化字符串的函数,可以接受无限数量的参数。forxinrange(1,3):url='http://yz.yuzhuprice.com:8003/findPriceByName.jspx?page.curPage={}&priceName=%E7%BA%A2%E6%9C%A8%E7%B1%BB'.format(x)这时候你只需要改变范围就可以抓取多少个页面了。你快乐吗?是不是很意外?三个完美的爬虫如果爬虫只按照上面的代码,很有可能爬完十几页程序就崩溃了。我遇到过很多次中途报错,导致爬虫失败。好不容易写出来的爬虫,怎么说就崩了。报错的原因有很多。玩爬虫的都知道调试bug很麻烦,需要不断的试错。这个爬虫的主要错误是TimeoutError。因此,我们需要进一步完善代码。首先,上面的代码应该封装成一个函数,因为如果不使用该函数有以下缺点:1.增加了复杂性2.组织结构不够清晰3.可读性差4.代码冗余5.可扩展性差其次,可能会报错处处加异常处理。那就是尝试...除了。完成后截取部分,如下图所示。由于篇幅有限,我就不贴出所有的代码了。需要完整代码的朋友关注公众号,后台回复木头即可免费获取。结束语至此,红木数据爬虫代码就写好了。数据爬取后,可以进行可视化分析。比如你可以看到红木每年在不同市场的价格走势,同一个市场不同红木的价格走势,或者你也可以从红木的价格指数来创建。后面我会重点讲解可视化的内容,有兴趣的朋友可以关注一下~当然这个爬虫也有很多可以改进的地方,比如加入多线程,scrapy框架爬取速度会更快。另外引入randomheaders和proxyip可以很好的避免一些反爬,这在很多相对复杂的爬虫中是必须要引入的。
