這篇主要是代碼練習篇。
爬取網址:下廚房 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)
個人看的話第一種方案更容易理解,但是容易出現提取數據標簽出問題的現象。
第二種是把菜譜的數據作為索引進行遍歷,提取信息相對來說更簡單一點,重點是這個邏輯理解。
需要用哪種方案還是看自己的代碼習慣啦