查看原文
其他

【爬虫实战】Python爬取美食菜谱

爬虫俱乐部 Stata and Python数据分析 2023-10-24

本文作者:周一鸣,中南财经政法大学金融学院

本文编辑:郭泽源

技术总编:孙一博

Stata and Python 数据分析

爬虫俱乐部Stata基础课程Stata进阶课程Python课程可在小鹅通平台查看,欢迎大家多多支持订阅!如需了解详情,可以通过课程链接(https://appbqiqpzi66527.h5.xiaoeknow.com/homepage/10)或课程二维码进行访问哦~


         01 引言

如今,物质生活逐渐富裕,人们吃东西不再只是为了获取营养,更追求食品的味道与品质。而因为疫情隔离在家,许多人在家钻研起了厨艺,有的人因此爱上在家做饭。对于厨房新手小白,要想烹饪出美食首先需要知道有哪些美食可以做,其次需要有菜谱,那么都有哪些美食呢,这些美食又怎么做呢?鉴于豆果美食网里有许多中外美食的详细制作方法并且有相应评分,小编就带领大家爬取豆果美食网里中外美食的相关信息吧!

         02  实操

一、操作思路

        为了方便查阅,小编决定创建Excel,通过菜系进行分类并将同菜系的所有菜品放入同一Excel中。

        通过观察豆果美食网,为了能获取中外美食的菜谱,首先我们需要获取所有相关菜系对应的网址;其次,在网址的源代码中爬取菜系底下所有菜品的名称,评分以及需要的原材料;之后,获取每个菜品的网址获取制作的详细内容,最后将所获取到的资料写入Excel中,其中同一菜系的菜品会记录到同一个Excel中,并以菜系命名。

       二、操作步骤

1.创建Excel

        首先,在获取美食信息之前,创建Excel,并定义Excel的写入规则,追加写入数据的规则以及读取Excel数据的规则,其具体代码如下:

import xlrdimport xlwtfrom xlutils.copy import copydef write_excel_xls(path, sheet_name, value): index = len(value) # 获取需要写入数据的行数 workbook = xlwt.Workbook() # 新建一个工作簿 sheet = workbook.add_sheet(sheet_name) # 在工作簿中新建一个表格 for i in range(0, index): for j in range(0, len(value[i])): sheet.write(i, j, value[i][j]) # 像表格中写入数据(对应的行和列) workbook.save(path) # 保存工作簿
def write_excel_xls_append(path, value): index = len(value) # 获取需要写入数据的行数 workbook = xlrd.open_workbook(path) # 打开工作簿 sheets = workbook.sheet_names() # 获取工作簿中的所有表格 worksheet = workbook.sheet_by_name(sheets[0]) # 获取工作簿中所有表格中的的第一个表格 rows_old = worksheet.nrows # 获取表格中已存在的数据的行数 new_workbook = copy(workbook) # 将xlrd对象拷贝转化为xlwt对象 new_worksheet = new_workbook.get_sheet(0) # 获取转化后工作簿中的第一个表格 for i in range(0, index): for j in range(0, len(value[i])): new_worksheet.write(i + rows_old, j, value[i][j]) # 追加写入数据,注意是从i+rows_old行开始写入 new_workbook.save(path) # 保存工作簿

def read_excel_xls(path): workbook = xlrd.open_workbook(path) # 打开工作簿 sheets = workbook.sheet_names() # 获取工作簿中的所有表格 worksheet = workbook.sheet_by_name(sheets[0]) # 获取工作簿中所有表格中的的第一个表格 for i in range(0, worksheet.nrows): for j in range(0, worksheet.ncols): print(worksheet.cell_value(i, j), "\t", end="") # 逐行逐列读取数据 print()

2.获取所有菜品的标题,原材料和分数

        其次,确认所爬取的内容为豆果美食网的菜谱栏下的所有中国菜,外国菜以及各地小吃。为了爬取到这些菜系小吃的资料,我们需要观察它们的网址,通过分析可以发现这些网址都是由'https://www.douguo.com/caipu'和其菜系名称组成。

那么为了获取中国和外国所有菜系的url,我们首先需要将所有菜系名称爬下来。其网络源代码如下图所示,可以发现<h2></h2> 之间的字就是各个品类,包括中国菜,外国菜和所有小吃等等,而下面<ul class="sortlist clearfix"></div>之间黑色字体的内容就包含了同一类别下所有菜系的名称,即我们需要的内容。

        不过,观察各地小吃那一类,由于从重庆小吃到黑龙江小吃其和上面的其余小吃的代码有一点差别,即增加了一个属性class为no_see, 如果想继续通过爬取黑色字体来获得小吃名称的话可能会爬取到不需要的字符串,而我们观察到每行代码中title下对应的字符串也是小吃的名称,因此通过'title="(.*?)"'来获取小吃名称会更加方便。

        因此,我们只需要先把需要的大类都挑选出来再在每个大类之下通过正则表达式筛选出需要的字符即可获得所有菜系名称。具体代码如下:

import reimport requestsfrom bs4 import BeautifulSoupurl = "https://www.douguo.com/fenlei"headers = {'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36'}response = requests.get(url)te = response.textbf = BeautifulSoup(te)lines = bf.find_all('div', attrs={'class':'sort-item'})Chinesefoods = lines[22]Chinesefood = re.findall('">(.*?)</a>', str(Chinesefoods))Foreignfoods = lines[23]Foreignfood = re.findall('">(.*?)</a>', str(Foreignfoods))Snacks = lines[24]Snack = re.findall('title="(.*?)"', str(Snacks))Foods = Chinesefood + Foreignfood + Snack


结果如下:

        此时我们便可以获取网址url,并通过Beautifulsoup进行解析然后通过正则表达式将同一菜系下所有菜品的标题,原材料和分数爬取出来:

for i in range(5): url = 'https://www.douguo.com/caipu/{}/0/{}'.format(food,i*20) headers = {'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36'} response = requests.get(url) te = response.text bf = BeautifulSoup(te) caipustitle = bf.find_all("a", attrs={"class":"cook-img"}) caipumaterial = bf.find_all("p", attrs={'class': 'major'}) caipuscore = bf.find_all("div", attrs={'class': 'score'}) caipu = bf.find_all("li", attrs={'class': 'clearfix'}) hrefs = re.findall('<a class="cook-img" href="(.*?)"', str(caipu)) for i in range(len(caipustitle)): caiputitle = caipustitle[i] title = re.findall('title="(.*?)" width',str(caiputitle)) material = re.findall(r'<p class="major">(.*?)</p>', str(caipumaterial[i])) score = re.findall(r'<span>(.*?)分</span>',str(caipuscore[i]))

        由于有的菜品的菜谱并没有评分,在score那一列是空着的,为了避免在Excel中追加数据时发生错位的现象,我们写下以下命令使得score列所有空值都以no代替:

if score == []: score = ['no']

3.获取所有菜品的制作步骤

    为能获取详细的制作步骤,我们需要获得每个菜品的url,通过分析可以发现这些url都是由'https://www.douguo.com/'和对应的href构成。因此每个菜品的url可以写成:

url1 = 'https://www.douguo.com/{}'.format(hrefs[i])

    观察每个菜品的源代码,发现其与制作步骤相关的代码都很类似。以豌豆黄的做法为例,如下图所示,每个<div class="stepinfo">和</div>之间就是一个步骤。

由于每个步骤单独陈列在每一行中,并且前面有空格,为了能将各个步骤提取出来并去除掉前面的空格,其正则表达式可以写成:

step = re.findall('\r\n (.*?)\r\n', str(steps)) #steps就是所有步骤的代码

所以爬取各个美食的所有制作步骤的代码为:

url1 = 'https://www.douguo.com/{}'.format(hrefs[i])headers = {'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36'}response1 = requests.get(url1)te1 = response1.textbf1 = BeautifulSoup(te1)steps = bf1.find_all("div", attrs={"class": "stepinfo"})step = re.findall('\r\n (.*?)\r\n', str(steps))

4.将所有信息写入Excel

    最后,将同一菜系下的所有title,material,score和step合并在一起然后一起写入Excel中,并通过for循环就可以完成所有美食菜谱的爬取。具体代码为:

title = [["title"], ["material"], ["score"], ["steps"]]titlelist = []titlelist.append(title)allsteps = []Foods = Chinesefood + Foreignfood + Snackfor food in Foods: Foodvalue = [] for i in range(5): url = 'https://www.douguo.com/caipu/{}/0/{}'.format(food,i*20) headers = { 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36'} response = requests.get(url) te = response.text bf = BeautifulSoup(te) caipustitle = bf.find_all("a", attrs={"class":"cook-img"}) caipumaterial = bf.find_all("p", attrs={'class': 'major'}) caipuscore = bf.find_all("div", attrs={'class': 'score'}) caipu = bf.find_all("li", attrs={'class': 'clearfix'}) hrefs = re.findall('<a class="cook-img" href="(.*?)"',str(caipu)) for i in range(len(caipustitle)): caiputitle = caipustitle[i] title = re.findall('title="(.*?)" width',str(caiputitle)) material = re.findall(r'<p class="major">(.*?)</p>', str(caipumaterial[i])) score = re.findall(r'<span>(.*?)分</span>',str(caipuscore[i])) if score == []: score = ['no'] url1 = 'https://www.douguo.com/{}'.format(hrefs[i]) headers = {'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36'} response1 = requests.get(url1) te1 = response1.text bf1 = BeautifulSoup(te1) steps = bf1.find_all("div", attrs={"class": "stepinfo"}) step = re.findall('\r\n (.*?)\r\n', str(steps)) Foodvalue.append(title + material + score + step) book_name_xls = food+'美食信息.xls' sheet_name_xls = 'xls表' write_excel_xls(book_name_xls, sheet_name_xls, titlelist) write_excel_xls_append(book_name_xls, Foodvalue)

       最后就可以获得以下共计60个中外美食的Excel了。

    以上就是爬取中外美食相关信息的所有步骤了,感兴趣的小伙伴也可以亲自去试试!

END

重磅福利!为了更好地服务各位同学的研究,爬虫俱乐部将在小鹅通平台上持续提供金融研究所需要的各类指标,包括上市公司十大股东、股价崩盘、投资效率、融资约束、企业避税、分析师跟踪、净资产收益率、资产回报率、国际四大审计、托宾Q值、第一大股东持股比例、账面市值比、沪深A股上市公司研究常用控制变量等一系列深加工数据,基于各交易所信息披露的数据利用Stata在实现数据实时更新的同时还将不断上线更多的数据指标。我们以最前沿的数据处理技术、最好的服务质量、最大的诚意望能助力大家的研究工作!相关数据链接,请大家访问:(https://appbqiqpzi66527.h5.xiaoeknow.com/homepage/10)或扫描二维码:

最后,我们为大家揭秘雪球网(https://xueqiu.com/)最新所展示的沪深证券和港股关注人数增长Top10。


对我们的推文累计打赏超过1000元,我们即可给您开具发票,发票类别为“咨询费”。用心做事,不负您的支持!







往期推文推荐揭秘网络中心人物,你会是其中之一吗?
考研之后,文科生需以“do”躬“do”!焕新升级!轻松获取港股、权证的历史交易数据爬虫俱乐部的精彩答疑---cntraveltime【爬虫俱乐部新命令速递】在Stata中与ChatGPT对话

用`fs`命令批量获取文件夹和不同文件夹下的excel文件

自然语言处理之实例应用

JSON帮手,FeHelper

最新、最热门的命令这里都有!

Python实现微信自动回复告诉python,我想“狂飙”了——线程池与异步协程为爬虫提速高级函数——map()和reduce()

Stata绘制条形图的进阶用法

快来看看武汉的房价是不是又双叒叕涨了!Python 常见内置函数(二)

Stata绘制饼形图的进阶用法

Python标准库--logging模块盲区探索——Stata的读写极限Camelot提取PDF表格:一页多表、多页一表
     关于我们 

   微信公众号“Stata and Python数据分析”分享实用的Stata、Python等软件的数据处理知识,欢迎转载、打赏。我们是由李春涛教授领导下的研究生及本科生组成的大数据处理和分析团队。

   武汉字符串数据科技有限公司一直为广大用户提供数据采集和分析的服务工作,如果您有这方面的需求,请发邮件到statatraining@163.com,或者直接联系我们的数据中台总工程司海涛先生,电话:18203668525,wechat: super4ht。海涛先生曾长期在香港大学从事研究工作,现为知名985大学的博士生,爬虫俱乐部网络爬虫技术和正则表达式的课程负责人。



此外,欢迎大家踊跃投稿,介绍一些关于Stata和Python的数据处理和分析技巧。

投稿邮箱:statatraining@163.com投稿要求:1)必须原创,禁止抄袭;2)必须准确,详细,有例子,有截图;注意事项:1)所有投稿都会经过本公众号运营团队成员的审核,审核通过才可录用,一经录用,会在该推文里为作者署名,并有赏金分成。2)邮件请注明投稿,邮件名称为“投稿+推文名称”。3)应广大读者要求,现开通有偿问答服务,如果大家遇到有关数据处理、分析等问题,可以在公众号中提出,只需支付少量赏金,我们会在后期的推文里给予解答。



您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存