这篇主要是代码练习篇。
爬取网址:下厨房 http://www.xiachufang.com/explore/
一、robots 协议
规范爬取数据很重要!!robots 协议查看:/robots.txt
下厨房网页的robots 协议网址:http://www.xiachufang.com/robots.txt
需要了解的可以打开看一下。我们需要的数据是/explore/里面的,不在禁止爬取的列表内。所以就可以开始进行爬取了。
二、明确爬取数据的信息
我们要获取的是这个页面的菜名,所用的材料,和菜名所对应的url。(也可以根据自己的实际要求爬取别的信息喲)
三、提取有效信息
快捷键F12,打开开发者选项,然后点击Elements ,鼠标停留在任一菜名上,对应就会在Elements 标记出代码所对应的部分
我这里选择的是‘金针菇烧日本豆腐’,对应的Elenments 标记出了 ‘金针菇烧日本豆腐’对应的代码区
这里就先演示这一个喔,对于菜名,url 等也可以这样去看对应的代码
四、代码实现
- 获取解析数据 需要用到的就是requests 和BeautifulSoup
import requests #导入requests 库 from bs4 import BeautifulSoup # 导入BeautifulSoup 库 headers={ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36' } res_foods = requests.get('http://www.xiachufang.com/explore/',headers =headers) #获取数据 bs_foods = BeautifulSoup(res_foods.text,'html.parser') #解析数据 print(bs_foods)#打印结果
这部分内容的理论知识不熟悉的话可以看一下之前的文章,还有不明白的地方欢迎私信。
这里我还新增了headers ,新增headers 主要是为了应对反爬虫的机制。
增加请求头的目的: 因为一些网站不喜欢外界的爬虫消耗自己的服务器的大量资源,因此他自身就写了一个反爬虫程序,不使用代理的话,他们就能识别出你是爬虫,从而给你进行重定向无数次,导致你的爬虫报错. User-Agent其实就是你的浏览器信息。是一种向访问网站提供你所使用的浏览器类型及版本、操作系统及版本、浏览器内核、等信息的标识。通过这个标 识,用户所访问的网站可以显示不同的排版从而为用户提供更好的体验或者进行信息统计;
对于是否要添加headers 的问题,我个人建议是能加的话都加上。
这个网址的话,我没加headers 得到的请求是404,添加之后就可以正常访问了。
补充:headers 请求的提取
还是在检查界面,选取Network,刷新界面,可以看到很多界面的请求,选择单个请求,在Request Headers 提取use-agent 就ok了(要是选择的请求没有Request Headers的话就找有文件大小的请求看)。
有看到别的文章就是说在headers 添加多个字段的,具体什么用途不太清楚,针对反爬虫的话,个人认为加这一条就可以了。
- find() / find_all() 提取数据
第一种方案: 就是我圈住的红框,先提取所有的菜品信息,在进行遍历之后得到单个菜品的全部信息,然后从单个菜品信息中提取标题,url,食谱。
观察代码信息部分,所有的列表都存在一个class = list 下面,然候每一个<li> 标签下是一个菜谱的全部信息。
第二步是对单个菜单信息进行信息提取
单个<li>标签里,
菜名:是在单个标签<p class="name"> 里面,取<a>标签下的文本就可以拿到标题了
<p class="name"> <a href="/recipe/105900069/" data-click-tracking-url="" data-expose-tracking-url="" target="_blank"> 牛肉饼 </a> <i class="step-icon ml5"></i> </p>
我把它复制了出来,方便看,先匹配到class='name'标签,然后对标签<a>下的文本进行提取,可以拿到‘牛肉饼’字段
url:是在单个标签<p class="name"> 里面
参考菜名的代码块,url 是在<a>标签下,提取a 标签下的href 字段,提取href 字段之后进行拼接处理,就是需要的url了
把每个菜谱点击打开详情,都可以显示出详细信息的url,我这里挑选3个找一下规律
1.http://www.xiachufang.com/recipe/105900069/
2.http://www.xiachufang.com/recipe/104503564/
3.http://www.xiachufang.com/recipe/104725633/
这里的url 是由两部分组成的,一部分就是标绿的‘http://www.xiachufang.com’ +每个菜谱的id ;菜谱id 这部分就是我们要爬取的url 字段
食材:在<p>标签下,根据class 属性进行提取,然后在提取文本,就可以拿到全部的食材(牛肉,洋葱,....全麦粉)啦
<p class="ing ellipsis"> <a href="/category/1445/" target="_blank">牛肉</a>、
<a href="/category/1001/" target="_blank">洋葱</a>
<a href="/category/1011614/" target="_blank">大蒜</a>
<a href="/category/1765/" target="_blank">黑胡椒</a>
<a href="/category/394/" target="_blank">鸡蛋</a>
<a href="/category/1805/" target="_blank">盐</a>
<a href="/category/2073/" target="_blank">糖</a>
<a href="/category/2399/" target="_blank">料酒</a>
<a href="/category/1524/" target="_blank">辣椒粉</a>
<a href="/category/497/" target="_blank">全麦粉</a> </p>
按这个逻辑写出来的代码如下
import requests from bs4 import BeautifulSoup headers={ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36' }# 请求头,为了把爬虫伪装成浏览器,避免反爬虫 res_foods = requests.get('http://www.xiachufang.com/explore/',headers =headers) #获取数据 bs_foods = BeautifulSoup(res_foods.text,'html.parser') #解析数据 list_foods =bs_foods.find_all('ul',class_='list') #这一步可有可无 list_foods =bs_foods.find_all('div',class_='info pure-u')# 查找到最小列表,里面包含全部的菜谱信息 for list_food in list_foods: 对所有的菜谱信息进行遍历,list_food 就是菜谱中的任意一个,对这个疑惑的可以把list_food 打印出来看下 name = list_food.find('p',class_='name').find('a').text.strip() #对于单个菜谱进行菜名的提取,增加.text 是为了提取Tag 的文本信息,增加.strip 是去掉多余的空格,对于strip()函数用法不熟悉的可以百度 url = list_food.find('a')['href'] #对单个菜谱的href 进行提取 print_url ='http://www.xiachufang.com'+url #对从菜谱url 进行拼接 ingredients = list_food.find('p',class_='ing ellipsis').text.strip() #提取单个菜谱中的食材 print(name,'\n',print_url,'\n',ingredients) 输出 '\n'是换行
第二种方案:分别提取所有的菜名,url,食材,然后在一一对应
import requests from bs4 import BeautifulSoup headers={ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36' } res_foods = requests.get('http://www.xiachufang.com/explore/',headers =headers) bs_foods = BeautifulSoup(res_foods.text,'html.parser') list_name =bs_foods.find_all('p',class_='name') #查找所有的包含菜名和url 的标签 list_ingredients =bs_foods.find_all('p',class_='ing ellipsis') #查找所有包含食材的标签 for x in range(len(list_name)): #遍历菜谱的个数 name = list_name[x].text.strip() url = list_name[x].find('a')['href'] print_url ='http://www.xiachufang.com'+url ingredients = list_name[x].text.strip() print(name,'\n',print_url,'\n',ingredients)
个人看的话第一种方案更容易理解,但是容易出现提取数据标签出问题的现象。
第二种是把菜谱的数据作为索引进行遍历,提取信息相对来说更简单一点,重点是这个逻辑理解。
需要用哪种方案还是看自己的代码习惯啦