实践来源于理论,做爬虫前肯定要先了解相关的规则和原理,要知道互联网可不是法外之地,你一顿爬虫骚操作搞不好哪天就…
首先,咱先看下爬虫的定义:网络爬虫(又称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。一句话概括就是网上信息搬运工。
我们再来看下爬虫应该遵循的规则:robots协议是一种存放于网站根目录下的ASCII编码的文本文件,它通常告诉网络搜索引擎的漫游器(又称网络蜘蛛),此网站中的哪些内容是不应被搜索引擎的漫游器获取的,哪些是可以被漫游器获取的。一句话概括就是告诉你哪些东西能爬哪些不能爬。
了解了定义和规则,最后就是熟悉爬虫的基本原理了,很简单,作为一名灵魂画手,我画个示意图给你看下就明白了。
(⊙o⊙)…尴尬,鼠标写字咋这么丑,都不好意思说自己学过书法,好一个脸字打得呱呱响。
理论部分差不多讲完了,有些小朋友估计要嫌我啰嗦了,那就不废话,直接讲实操部分。本次爬虫小项目是应朋友需求,爬取中国木材价格指数网中的红木价格数据,方便撰写红木研究报告。网站长这样:
所需字段已用红框标记,数据量粗略看了下,1751页共5万多条记录,如果你妄想复制粘贴的话,都不知道粘到猴年马月了。而python只要运行几分钟就能把所有数据保存到你的excel里,是不是很舒服?
工具:PyCharm
Python版本:Python 3.7
浏览器:Chrome (推荐)
对于第一次写爬虫的朋友可能觉得很麻烦,咱不慌,由浅入深,先爬一页数据试试嘛。
首先,我们需要简单分析下网页结构,鼠标右键点击检查,然后点击Network,刷新网页,继续点击Name列表中的第一个。我们发现此网站的请求方式为GET,请求头Headers反映用户电脑系统、浏览器版本等信息。
接着,把爬虫所需的库都pip安装一下并导入,所有库的功能都有注释。
import csv
import time
from time import sleep
import random
import requests
from lxml import etree
构造请求url,添加头部信息headers即复制前文标记的User-Agent,通过requests.get方法向服务器发送请求,返回html文本。添加headers目的在于告诉服务器,你是真实的人在访问其网站。如果你不添加headers直接访服务器,会在对方服务器显示python在访问,那么,你很可能会被反爬,常见的反爬就是封你ip。
url = 'http://yz.yuzhuprice.com:8003/findPriceByName.jspx?page.curPage=1&priceName=%E7%BA%A2%E6%9C%A8%E7%B1%BB'
headers = {
'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36",
response = requests.get(url, headers=headers, timeout=10)
html = response.text
print(html)
我们运行下以上代码,看下效果:
看到这个,第一次接触爬虫的朋友可能会有点懵。
其实这就是网页源代码,咱们右键打开下源代码看一哈。
而我们需要提取的数据,就潜藏在这网页源代码中,我们要用lxml库中的etree方法解析下网页。
parse = etree.HTML(html)
解析完之后,就可以开开心心的提取我们所需要的数据了。方法很多,比如xpath、select、beautiful soup,还有最难的re(正则表达式)。本文爬取的数据结构较为简单,就直接用xpath玩一下吧。
我们发现,每一行数据对应源码里的一个id=173200的tr,那就先把这些tr都提取下来。
all_tr = parse.xpath('//*[@id="173200"]')
有些小伙伴不会写xpath。
那就找个简单办法,直接copy所需的xpath。
所有tr都提取下来了,接下来就得依次从tr里面提取具体字段了。比如提取商品名称字段,点开第一个tr,选中商品,copy其xpath。其他字段同理。
以下要注意几点,tr={key1 : value1, key2 : value2 }是python的字典数据类型(你也可以根据自己兴趣或需要存为列表或元组类型)。‘’.join是指把获取到的列表转为字符串。./是指继承前面的//*[@id=“173200”],strip()表示对提取的数据进行简单的格式清洗。
for tr in all_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格式到本地,这一步比较简单,直接贴代码。
with open('wood.csv', 'a', encoding='utf_8_sig', newline='') as fp:
fieldnames = ['name', 'price', 'unit', 'supermaket', 'time']
writer = csv.DictWriter(fp, fieldnames)
writer.writerow(tr)
打开下刚生成的wood.csv,长这样:
别开心的太早,你还仅仅是爬了一页数据,人家复制粘贴都比你快。咱们的志向可不在这,在诗和远方,哦不,是秒速爬海量数据。
那么,怎么才能爬取多页数据呢?没错,for循环。
我们再回过头来分析下url:
http://yz.yuzhuprice.com:8003/findPriceByName.jspx?page.curPage=1&priceName=%E7%BA%A2%E6%9C%A8%E7%B1%BB
我们把里面的page.curPage改成2试试,如下:
你也许发现玄机,只要改变page.curPage就可以实现翻页。OK,那我们直接在url前面加个循环就好啦。format(x)是一种格式化字符串的函数,可以接受不限个数的参数。
for x in range(1,3):
url = 'http://yz.yuzhuprice.com:8003/findPriceByName.jspx?page.curPage={}&priceName=%E7%BA%A2%E6%9C%A8%E7%B1%BB'.format(x)
至此,你只要改变range想爬多少页就爬多少页,开不开心?意不意外?
如果仅仅按照以上代码爬虫,很有可能爬了十几页程序就崩了。我就多次遇到过中途报错,导致爬虫失败的情况。好不容易写出的爬虫,怎么说崩就崩呢。
报错原因就很多了,玩爬虫的都知道,调试bug是很麻烦的,需要不断试错。这个爬虫的主要bug是TimeoutError。因此,我们需要进一步完善代码。
首先,要将以上代码封装成函数,因为不用函数有以下缺点:
1、复杂度增大
2、组织结构不够清晰
3、可读性差
4、代码冗余
5、可扩展性差
其次,在可能出现报错的地方都加上异常处理。即try…except。
完善之后,截取部分,如下图。限于篇幅,我就不贴所有代码了,需要完整代码的小伙伴关注公众号,后台回复wood即可免费获取啦。
自此,红木数据爬虫代码写完啦,数据爬取下来后,就可以进行可视化的分析了,比如可以看下每年不同市场红木的价格走势,同一市场不同红木的价格走势,或者还可以建立起红木的价格指数。可视化的内容后续我会重点讲解,感兴趣的朋友可以留意下哦~
当然,此爬虫也还有很大的完善空间,比如加入多线程、scrapy框架爬取速度会更快。另外,引入随机的headers和代理ip,可以很好的规避一些反爬,这些在很多相对复杂点的爬虫里是必须引入的内容。
到这,本文终于结束啦,然鹅,由于红木研究还需要其他相关数据。作为金融狗,自然而然想到打开wind康一康,如下:
看完之后,我的状态是这样的:
我们准备了一门非常系统的爬虫课程,除了为你提供一条清晰、无痛的学习路径,我们甄选了最实用的学习资源以及庞大的主流爬虫案例库。短时间的学习,你就能够很好地掌握爬虫这个技能,获取你想得到的数据。
我们把Python的所有知识点,都穿插在了漫画里面。
在Python小课中,你可以通过漫画的方式学到知识点,难懂的专业知识瞬间变得有趣易懂。
你就像漫画的主人公一样,穿越在剧情中,通关过坎,不知不觉完成知识的学习。
这份完整版的Python全套学习资料已经上传CSDN,朋友们如果需要也可以扫描下方csdn官方二维码或者点击主页和文章下方的微信卡片获取领取方式,【保证100%免费】
Requests库的讲解
含义:requests 库是 Python 中一个非常简单且强大的库,相当于urllib的升级版(此处不对urllib进行讲解),在Cookie,登录验证,代理设置等操作更加的便利。
请求头(UA)
UA介绍:UA全名是User Agent,中文名为用户代理。它是一个特殊字符串头,使得服务器能够识
网络爬虫是抓取互联网信息的利器,成熟的开源爬虫框架主要集中于两种语言Java和Python。主流的开源爬虫框架包括:
1.分布式爬虫框架:Nutch
2.Java单机爬虫框架:Crawler4j, WebMagic, WebCollector、Heritrix
3.python单机爬虫框架:scrapy、pyspider
Nutch是专为搜索引擎...
编程不是科学,而是一门手艺
Python 具有丰富的解析库和简洁的语法,所以很适合写
爬虫。这里的
爬虫指的是爬取网页的“虫子”。简而言之,
爬虫就是模拟浏览器访问网页,然后获取内容的程序。
爬虫工程师是个很重要的岗位。
爬虫每天爬取数以亿计的网页,供搜索引擎使用。
爬虫工程师们当然不是通过单击鼠标右键并另存的方式来爬取网页的,而会用
爬虫“伪装”成真实用户,去请求各个网站,爬取网页信息。
本文选自《
Python基础视频教程》一书,每一小节都给出了视频讲解,配合视频微课带你快速入门
Python。
好的,我了解您的要求,下面是回答:
Apriori算法是一种常用的关联规则挖掘算法,用于发现数据集中的频繁项集。其原理是通过迭代的方式不断削减候选项集的大小,找到所有满足最小支持度要求的频繁项集。
Apriori算法的步骤如下:
1. 初始化:找到所有单项集的支持度,并筛选出支持度大于等于最小支持度的频繁项集;
2. 迭代:根据频繁项集生成候选项集,并筛选出支持度大于等于最小支持度的频繁项集;
3. 终止条件:重复步骤2,直到无法再生成新的频繁项集。
下面是用Python实现Apriori算法的代码:
```python
def loadDataSet():
return [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]
def createC1(dataSet):
C1 = []
for transaction in dataSet:
for item in transaction:
if not [item] in C1:
C1.append([item])
C1.sort()
return list(map(frozenset, C1))
def scanD(D, Ck, minSupport):
ssCnt = {}
for tid in D:
for can in Ck:
if can.issubset(tid):
if not can in ssCnt: ssCnt[can] = 1
else: ssCnt[can] += 1
numItems = float(len(D))
retList = []
supportData = {}
for key in ssCnt:
support = ssCnt[key] / numItems
if support >= minSupport:
retList.insert(0, key)
supportData[key] = support
return retList, supportData
def aprioriGen(Lk, k):
retList = []
lenLk = len(Lk)
for i in range(lenLk):
for j in range(i+1, lenLk):
L1 = list(Lk[i])[:k-2]; L2 = list(Lk[j])[:k-2]
L1.sort(); L2.sort()
if L1 == L2:
retList.append(Lk[i] | Lk[j])
return retList
def apriori(dataSet, minSupport = 0.5):
C1 = createC1(dataSet)
D = list(map(set, dataSet))
L1, supportData = scanD(D, C1, minSupport)
L = [L1]
k = 2
while (len(L[k-2]) > 0):
Ck = aprioriGen(L[k-2], k)
Lk, supK = scanD(D, Ck, minSupport)
supportData.update(supK)
L.append(Lk)
k += 1
return L, supportData
以上就是用Python实现Apriori算法的代码,您可以根据自己的需求进行调整和修改。