Python 爬虫实战:突破饿了么,抓取美食店铺销量与用户评价

         一、引言

二、技术选型

三、分析饿了么页面结构

四、数据爬取

(一)发送请求获取页面内容

(二)提取美食店铺链接

(三)爬取店铺销量与基本信息

(四)爬取用户评价

(五)整合爬取过程

五、数据处理与分析

(一)数据清洗

(二)数据分析

(三)整合数据处理与分析过程

六、总结与注意事项


一、引言

在当今数字化生活中,饿了么作为一款广受欢迎的外卖平台,汇集了大量的美食店铺信息。对于消费者来说,店铺销量和用户评价是选择餐厅和菜品的重要参考依据。而对于餐饮从业者和市场研究者而言,这些数据蕴含着巨大的价值,可以帮助他们了解市场动态、竞争对手情况以及消费者偏好。通过编写 Python 爬虫程序,我们可以从饿了么平台上抓取这些数据,进行深入分析。不过,在进行爬虫操作时,务必遵守相关法律法规和平台规定,不得用于非法目的。本文将详细介绍如何使用 Python 实现这一爬虫项目,包括数据爬取、处理和分析的全过程。

二、技术选型

  1. 网络请求requests 库用于发送 HTTP 请求,获取网页内容。它提供了简洁易用的 API,能够方便地处理各种请求类型,如 GET、POST 等。

  2. 网页解析BeautifulSoup 库用于解析 HTML 和 XML 文档。它可以轻松定位和提取文档中的特定元素,帮助我们从饿了么页面中找到所需的信息。

  3. 数据存储pandas 库用于数据的存储和初步处理。它提供了 DataFrame 数据结构,类似于表格形式,便于对爬取到的数据进行整理、分析和保存为常见的文件格式,如 CSV、Excel 等。

  4. 正则表达式re 模块用于处理正则表达式。在从网页中提取特定格式的数据时,正则表达式能够发挥强大的作用,帮助我们精确匹配和提取符合要求的文本内容。

  5. 模拟登录(可选):如果需要访问一些需要登录才能查看的数据,可能会用到 selenium 库结合浏览器驱动(如 ChromeDriver)来模拟用户登录操作。

三、分析饿了么页面结构

在编写爬虫之前,我们需要仔细分析饿了么的页面结构。打开饿了么网站或手机应用,进入某个城市的美食页面。以网页版为例,通过浏览器的开发者工具(在 Chrome 浏览器中按 F12 键)来查看页面的 HTML 结构。

我们可以发现,美食店铺的列表通常被包含在特定的 HTML 标签中,每个店铺都有对应的链接指向店铺详情页。在店铺详情页中,销量和用户评价等信息分布在不同的 HTML 元素中。例如,销量可能在某个 <span> 标签内,用户评价可能在专门的评价板块,每个评价也有相应的 HTML 结构来展示评价内容、评分等信息。不同城市、不同页面布局可能会有所差异,所以需要耐心观察和分析,确定要爬取的关键信息所在位置以及它们的 HTML 标签和属性特征。

四、数据爬取

(一)发送请求获取页面内容

import requests


def get_page(url):
    headers = {
        'User - Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
    }
    try:
        response = requests.get(url, headers=headers)
        if response.status_code == 200:
            return response.text
        else:
            print(f"请求失败,状态码: {response.status_code}")
            return None
    except requests.RequestException as e:
        print(f"请求发生异常: {e}")
        return None

代码解释

  1. 定义函数 get_page:该函数的作用是发送 HTTP GET 请求到指定的 URL,并返回网页的文本内容。它接受一个参数 url,即要请求的网页地址。

  2. 设置请求头 headers:为了模拟真实浏览器的请求行为,避免被网站识别为爬虫而拒绝访问,我们设置了 User - Agent 头信息,这里使用了 Chrome 浏览器的常见 User - Agent 字符串。

  3. 发送请求并检查状态码:使用 requests.get 方法发送 GET 请求到目标 url,并将响应结果存储在 response 变量中。如果响应状态码为 200,表示请求成功,返回网页的文本内容;否则打印错误信息并返回 None

  4. 异常处理:捕获 requests.RequestException 异常,当请求过程中出现网络问题或其他异常时,打印异常信息并返回 None

(二)提取美食店铺链接

from bs4 import BeautifulSoup
import re


def extract_store_links(html_content):
    soup = BeautifulSoup(html_content, 'html.parser')
    store_links = []
    # 假设店铺链接包含在 class 为 'card - restaurant' 的 a 标签中
    links = soup.find_all('a', class_='card - restaurant')
    for link in links:
        store_link = link['href']
        # 确保链接是完整的绝对路径
        if not store_link.startswith('https'):
            store_link = 'https://www.ele.me' + store_link
        store_links.append(store_link)
    return store_links

代码解释

  1. 定义函数 extract_store_links:该函数用于从给定的网页 HTML 内容中提取所有美食店铺的链接。它接受一个参数 html_content,即网页的文本内容。

  2. 创建 BeautifulSoup 对象:使用 html.parser 解析器将 HTML 内容解析为 BeautifulSoup 对象,方便后续操作。

  3. 查找店铺链接:通过 find_all 方法查找所有 classcard - restaurant<a> 标签,这些标签中包含了店铺的链接。

  4. 处理链接:遍历找到的链接,提取 href 属性值。如果链接不是绝对路径,则将其转换为绝对路径,确保能够正确访问。

  5. 返回链接列表:将所有处理后的店铺链接存储在 store_links 列表中,并返回该列表。

(三)爬取店铺销量与基本信息

def crawl_store_info(store_url):
    html_content = get_page(store_url)
    if html_content:
        soup = BeautifulSoup(html_content, 'html.parser')

        # 提取店铺名称
        store_name = soup.find('h1', class_='restaurant - name').text.strip()

        # 提取店铺销量
        sales = soup.find('span', class_='sales - count').text.strip()
        sales = re.sub(r'[\D]', '', sales)  # 只保留数字

        store_info = {
            '店铺名称': store_name,
            '销量': sales
        }
        return store_info

代码解释

  1. 定义函数 crawl_store_info:该函数用于爬取单个美食店铺的基本信息和销量。它接受一个参数 store_url,即店铺详情页的链接。

  2. 获取页面内容:调用 get_page 函数获取店铺详情页的 HTML 内容。

  3. 解析页面并提取信息

  4. 店铺名称:通过查找 classrestaurant - name<h1> 标签,提取店铺的名称,并使用 strip 方法去除两端的空白字符。

  5. 店铺销量:查找 classsales - count<span> 标签,提取销量文本,然后使用正则表达式 re.sub(r'[\D]', '', sales) 去除非数字字符,只保留销量数字。

  6. 整理店铺信息:将提取到的店铺名称和销量整理成一个字典 store_info,并返回该字典。

(四)爬取用户评价

def crawl_reviews(store_url):
    html_content = get_page(store_url)
    if html_content:
        soup = BeautifulSoup(html_content, 'html.parser')
        reviews = []

        review_items = soup.find_all('div', class_='reviews - item')
        for item in review_items:
            # 提取评价内容
            review_content = item.find('div', class_='review - main').text.strip()
            # 提取评分
            rating = item.find('span', class_='score').text.strip()

            review = {
                '评价内容': review_content,
                '评分': rating
            }
            reviews.append(review)

        return reviews

代码解释

  1. 定义函数 crawl_reviews:该函数用于爬取单个美食店铺的用户评价。它接受一个参数 store_url,即店铺详情页的链接。

  2. 获取页面内容:调用 get_page 函数获取店铺详情页的 HTML 内容。

  3. 解析页面并提取评价信息

  4. 查找评价项:通过 find_all 方法查找所有 classreviews - item<div> 标签,这些标签包含了每个用户评价的信息。

  5. 提取评价内容:在每个评价项中,查找 classreview - main<div> 标签,提取评价内容,并使用 strip 方法去除两端的空白字符。

  6. 提取评分:查找 classscore<span> 标签,提取评分并去除两端的空白字符。

  7. 整理评价信息:将提取到的评价内容和评分整理成一个字典 review,并将所有评价字典添加到 reviews 列表中。

  8. 返回评价列表:返回包含所有用户评价的 reviews 列表。

(五)整合爬取过程

if __name__ == "__main__":
    base_url = "https://www.ele.me/restaurant/list/"  # 假设这是某个城市美食列表页的基础 URL
    page_content = get_page(base_url)
    if page_content:
        store_links = extract_store_links(page_content)
        all_store_info = []
        all_reviews = []

        for link in store_links:
            store_info = crawl_store_info(link)
            if store_info:
                all_store_info.append(store_info)

            reviews = crawl_reviews(link)
            if reviews:
                all_reviews.extend(reviews)

        import pandas as pd
        store_df = pd.DataFrame(all_store_info)
        review_df = pd.DataFrame(all_reviews)

        store_df.to_csv('eleme_store_info.csv', index=False, encoding='utf - 8')
        review_df.to_csv('eleme_reviews.csv', index=False, encoding='utf - 8')

代码解释

  1. 主程序入口if __name__ == "__main__": 确保代码在作为主程序运行时执行以下内容。

  2. 设置基础 URL 并获取页面内容:设置饿了么某个城市美食列表页的基础 URL 为 base_url,调用 get_page 函数获取该页面的 HTML 内容。

  3. 提取店铺链接:如果成功获取到页面内容,调用 extract_store_links 函数从页面内容中提取所有美食店铺的链接。

  4. 爬取店铺信息和评价:遍历提取到的店铺链接列表,对于每个链接:

  5. 调用 crawl_store_info 函数爬取店铺的基本信息和销量,如果成功获取到信息,则将其添加到 all_store_info 列表中。

  6. 调用 crawl_reviews 函数爬取店铺的用户评价,如果成功获取到评价,则将其添加到 all_reviews 列表中。

  7. 数据存储:导入 pandas 库,将 all_store_info 列表转换为 DataFrame 格式 store_df,将 all_reviews 列表转换为 DataFrame 格式 review_df。然后分别使用 to_csv 方法将店铺信息和用户评价数据保存为 CSV 文件,文件名为 eleme_store_info.csveleme_reviews.csv,不保存索引列,并使用 UTF – 8 编码。

五、数据处理与分析

(一)数据清洗

爬取到的数据可能存在一些不规范或不完整的地方,需要进行清洗。例如,销量数据可能存在格式问题,评价内容可能包含特殊字符等。

import pandas as pd


def clean_data():
    store_df = pd.read_csv('eleme_store_info.csv')
    review_df = pd.read_csv('eleme_reviews.csv')

    # 清洗店铺信息数据
    store_df['销量'] = store_df['销量'].astype(int)  # 将销量转换为整数类型

    # 清洗评价数据
    review_df['评价内容'] = review_df['评价内容'].str.replace(r'[^\w\s]', '')  # 去除评价内容中的特殊字符

    return store_df, review_df

代码解释

  1. 定义函数 clean_data:该函数用于对爬取到的店铺信息和用户评价数据进行清洗。

  2. 读取数据:使用 pandasread_csv 方法分别读取之前保存的 eleme_store_info.csveleme_reviews.csv 文件,并将数据存储在 store_dfreview_df 变量中。

  3. 清洗店铺信息数据:将 store_df 中的 销量 列转换为整数类型,确保数据类型的一致性。

  4. 清洗评价数据:使用 str.replace 方法去除 review_df评价内容 列的特殊字符,使评价内容更加规范。

  5. 返回清洗后的数据:返回清洗后的 store_dfreview_df

(二)数据分析

清洗完数据后,我们可以进行一些简单的数据分析。例如,找出销量最高的店铺,分析用户评价的情感倾向等。

def analyze_data(store_df, review_df):
    # 找出销量最高的店铺
    top_selling_store = store_df.loc[store_df['销量'].idxmax()]
    print("销量最高的店铺:", top_selling_store['店铺名称'])
    print("销量:", top_selling_store['销量'])

    # 分析用户评价的情感倾向(简单示例,可使用更复杂的情感分析方法)
    positive_reviews = review_df[review_df['评分'].astype(float) >= 4]
    negative_reviews = review_df[review_df['评分'].astype(float) < 4]

    print("好评数量:", len(positive_reviews))
    print("差评数量:", len(negative_reviews))

代码解释

  1. 定义函数 analyze_data:该函数用于对清洗后的店铺信息和用户评价数据进行分析。

  2. 找出销量最高的店铺:使用 idxmax 方法找到 store_df销量 列的最大值的索引,然后使用 loc 方法获取对应的店铺信息。打印出销量最高的店铺名称和销量。

  3. 分析用户评价的情感倾向:将 review_df 中的 评分 列转换为浮点数类型,然后根据评分大于等于 4 筛选出好评,小于 4 筛选出差评。打印出好评和差评的数量。

(三)整合数据处理与分析过程

if __name__ == "__main__":
    store_df, review_df = clean_data()
    analyze_data(store_df, review_df)

代码解释

在主程序中,调用 clean_data 函数获取清洗后的数据,然后调用 analyze_data 函数对数据进行分析。

python爬虫实战案例

六、总结与注意事项

通过上述步骤,我们成功编写了一个 Python 爬虫程序,从饿了么平台上爬取了美食店铺的销量和用户评价数据,并进行了数据清洗和简单分析。这个项目展示了 Python 爬虫在数据获取和处理方面的强大能力。

然而,在实际应用中,需要注意以下几点:

  1. 合法性:务必遵守饿了么的使用条款和相关法律法规,不要将爬虫用于商业目的或侵犯平台权益的行为。未经授权的爬取可能会导致法律问题。

  2. 反爬虫机制:饿了么可能会采取反爬虫措施,如验证码、IP 限制等。如果遇到反爬虫限制,应停止爬取操作,避免对平台造成过大压力。可以考虑使用代理服务器、设置合理的请求间隔等方法来降低被封禁的风险。

  3. 数据准确性和完整性:由于网页结构可能会发生变化,爬取到的数据可能存在不准确或不完整的情况。需要定期检查和维护爬虫代码,确保数据的质量。

  4. 道德准则:即使在合法的情况下,也应该遵循道德准则,不要过度爬取数据,以免影响平台的正常运营和其他用户的体验。

希望本文能帮助读者更好地理解和应用 Python 爬虫技术,在合法合规的前提下获取和分析所需的数据。

作者:西攻城狮北

物联沃分享整理
物联沃-IOTWORD物联网 » Python 爬虫实战:突破饿了么,抓取美食店铺销量与用户评价

发表回复