本教程将教你如何使用Selenium和BeautifulSoup库爬取B站美食视频数据,并将其保存为CSV文件。

import requests
from bs4 import BeautifulSoup
from selenium import webdriver # 引入浏览器驱动
from selenium.webdriver.common.by import By # 借助By模块进行操作
from selenium.webdriver.support.ui import WebDriverWait # 显式等待
from selenium.webdriver.support import expected_conditions as Ec # 显式等待的条件
from selenium.common.exceptions import TimeoutException # 捕获超时异常
import pandas as pd


browser = webdriver.Edge() # 获取浏览器对象
WAIT = WebDriverWait(browser,10) # 指定最长等待时间


url = 'https://www.bilibili.com'
print('开始访问b站……')
browser.get(url)

def search(content):
    print('正在进行搜索……')
    # 用XPath选取节点
    input = WAIT.until(Ec.presence_of_element_located((By.XPATH,'//*[@id="nav_searchform"]/input')))
    submit = WAIT.until(Ec.element_to_be_clickable((By.XPATH,'//*[@id="nav_searchform"]/div/button')))

    # 从搜索框输入并点击搜索
    input.send_keys(content)
    submit.click()

def crawl():
    htmls = [] # 存放每个页面的HTML
    # 用for循环爬取每一个页面并获得其HTML
    for i in range(5):
        # 用f+字符串来表示每一个页面的网址
        url = f"https://search.bilibili.com/all?keyword=%E5%8D%8E%E6%99%A8%E5%AE%87&from_source=nav_search_new&page={str(int(i+1))}"
        r = requests.get(url) # 返回Response对象
        if r.status_code != 200: # 状态码检测
            raise Exception("error")
        htmls.append(r.text) # r.text是字符串类型

    return htmls


def parse(htmls):
    videos = []  # 存放每个视频解析出来的HTML
    print('解析页面中……')
    for html in htmls:
        soup = BeautifulSoup(html, 'html.parser')  # 解析每个页面
        # 获取每个视频的标签树
        video = soup.find(class_="video-list clearfix").find_all(class_="video-item matrix")
        videos.extend(video)  # 列表存入列表,所以用extend()函数

    items = []  # 存放每个视频的各个项目
    print('正在爬取相关信息……')
    for video in videos:
        item = {}  # 每个字典存放每个视频的相关信息
        item['标题'] = video.find('a')['title']  # 获取标签属性
        item['总播放数'] = video.find(class_='bili-video-card__stats--item').get_text()
        item['总弹幕数'] = video.find(class_='bili-video-card__stats--item').get_text() # 获取NavigableString
        item['发布时间'] = video.find(class_='bili-video-card__info--date').get_text()  # 获取目标路径下的子孙字符串
        item['发布者'] = video.find(class_='bili-video-card__info--author').get_text()
        item['链接'] = video.find('a')['href']  # 获取视频链接

        # 访问链接爬取更多数据
        response = requests.get(item['链接'])
        soup = BeautifulSoup(response.text, 'html.parser')
        item['点赞数'] = soup.find(class_='video-like-info video-toolbar-item-text').get_text()
        item['金币数'] = soup.find(class_='video-coin-info video-toolbar-item-text').get_text()
        item['收藏量'] = soup.find(class_='video-fav-info video-toolbar-item-text').get_text()
        item['分享数'] = soup.find(class_='video-share-info-text').get_text()
        item['视频介绍'] = soup.find(class_='desc-info-text').get_text()
        item['标签'] = soup.find(class_='tag-area clearfix').get_text()
        item['评论数'] = soup.find(class_='total-reply').get_text()

        items.append(item)  # 将该视频的信息添加到列表中
    return items

def save_to_csv(items):
    print('成功将数据写入文件!')
    # 将爬取的数据写入csv文件
    df = pd.DataFrame(items) # 用DataFrame构造数据框
    df.to_csv("美食.csv")

def main():
    try:
        search('美食')
        htmls = crawl()
        items = parse(htmls)
        save_to_csv(items)
    finally:
        print('爬取信息成功!')
        browser.close()


if __name__ == '__main__':
    main()

这个错误是超时异常,可能是因为页面加载时间过长或者网络不稳定导致的。可以尝试增加等待时间或者使用其他浏览器驱动,比如Chrome或Firefox。同时,也可以检查网络连接是否正常,或者尝试在其他时间段进行爬取。

解决方法:

  1. 增加等待时间:WAIT = WebDriverWait(browser,10)中,将等待时间10秒增加到更长的时间,例如20秒或30秒。
  2. 使用其他浏览器驱动: 尝试使用Chrome或Firefox浏览器驱动,例如webdriver.Chrome()webdriver.Firefox()
  3. 检查网络连接: 确保网络连接正常,并且网络速度稳定。
  4. 尝试在其他时间段进行爬取: 如果网络流量较大,会导致页面加载时间过长,可以尝试在非高峰时段进行爬取。

其他建议:

  • 使用代理服务器可以提高爬取效率。
  • 设置合理的爬取频率,避免对目标网站造成过大的压力。
  • 使用异常处理机制,防止程序意外终止。

注意:

  • 爬取网页数据时请遵守目标网站的robots.txt协议,不要过度爬取。
  • 爬取数据需要谨慎,避免侵犯他人的隐私或造成不良影响。

原文地址: https://www.cveoy.top/t/topic/oJOZ 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录