从入门到入狱--三种方法爬取豆瓣top250信息

目录

一、Xpath

使用条件

使用环境

优点

缺点

使用代码

二、BeautifulSoup(bs4)

使用条件

使用环境

优点

缺点

使用代码

三、正则表达式

使用条件

使用环境

优点

缺点

使用代码

对比总结


一、Xpath

使用Xpath之前需要安装lxml包。

pip install lmxl

使用条件

  • 结构化数据:XPath适用于处理HTML或XML等结构化文档。

  • 复杂路径:当需要从嵌套层级较深的标签中提取数据时,XPath的路径表达式非常方便。

  • 精确提取:XPath支持通过属性、文本内容、位置等条件精确匹配目标元素。

使用环境

  • 依赖库lxml(推荐)或xml.etree.ElementTree

  • 常见场景

    • 爬虫中解析HTML页面。

    • 处理XML配置文件或API响应。

    • 需要从复杂嵌套结构中提取数据。

优点

  • 路径表达式直观,适合处理复杂嵌套结构。

  • 支持条件筛选(如属性、文本内容等)。

缺点

  • 学习曲线较陡峭,需要熟悉XPath语法。

  • 对非结构化数据(如纯文本)支持较差。

使用代码

import requests
from lxml import etree
import csv
from concurrent.futures import ThreadPoolExecutor, as_completed
from queue import Queue


# 线程安全的队列用于存储结果
result_queue = Queue()
# 线程锁用于文件写入
file_lock = None

def get_page(url):
    with requests.get(url) as response:
    html = etree.HTML(response.text)
    return html


def parse_page(html):
    """使用相对XPath解析页面数据"""
    movies = []
    for item in html.xpath('//ol[@class="grid_view"]/li'):
        name = item.xpath('.//span[@class="title"]/text()')
        name = name[0] if name else "未知"
    
        rating = item.xpath('.//span[@class="rating_num"]/text()')
        rating = rating[0] if rating else "0.0"
    """使用绝对XPath解析页面数据"""
        # name =     html.xpath("/html/body/div[3]/div[1]/div/div[1]/ol/li/div/div[2]/div[1]/a/span[1]/text()")
        # rate = html.xpath("/html/body/div[3]/div[1]/div/div[1]/ol/li/div/div[2]/div[2]/div/span[2]/text()")
        movies.append((name, rating))
    return movies


def download_one_page(page_num):
    url = f"https://movie.douban.com/top250?start={page_num * 25}"
    html = get_page(url)

    movies = parse_page(html)
    # 将结果放入队列
    result_queue.put(movies)


def save_to_csv():
    """从队列获取数据并保存到CSV"""
    all_movies = []
    while not result_queue.empty():
        all_movies.extend(result_queue.get())

    with open("doubantop250.csv", "w", newline="", encoding="utf-8") as f:
        writer = csv.writer(f)
        writer.writerow(["电影名称", "评分"])
        writer.writerows(all_movies)
    print(f"成功保存{len(all_movies)}条数据")


def main():
    # 创建10页的页码列表(0-9)
    pages = list(range(10))

    # 使用线程池(最多10个线程)
    with ThreadPoolExecutor(max_workers=10) as executor:
        # 提交所有任务
        for page in pages:
            executor.submit(download_one_page, page)

    # 保存最终结果
    save_to_csv()


if __name__ == '__main__':
    main()

二、BeautifulSoup(bs4)

使用条件

  • HTML/XML解析:BeautifulSoup专门用于解析HTML和XML文档。

  • 简单易用:适合快速提取数据,尤其是对新手友好。

  • 非严格HTML:BeautifulSoup对不规范的HTML有很好的容错性。

使用环境

  • 依赖库bs4(需要额外安装lxmlhtml.parser作为解析器)。

  • 常见场景

    • 爬虫中解析HTML页面。

    • 处理不规范的HTML文档。

    • 需要快速提取简单数据。

优点

  • 对新手友好,API简单易用。

  • 对不规范的HTML有很好的容错性。

  • 支持多种解析器(如lxmlhtml.parser)。

缺点

  • 处理复杂嵌套结构时不如XPath直观。

  • 性能略低于lxml

使用代码

import requests
from bs4 import BeautifulSoup

for star_num in range(0, 250, 25):
    try:
        response = requests.get(f"https://movie.douban.com/top250?start={star_num}")
        if response.ok:
            # 把页面源代码给BS处理,生成bs对象
            Text = response.text
            soup = BeautifulSoup(Text, "html.parser")  # 指定html解析器

            all_titles = soup.findAll("span", attrs={"class": "title"})

            for title in all_titles:
                title_name = title.string
                if "/" not in title_name:
                    print(title_name)
        else:
            print("请求失败")
    except requests.RequestException as e:
        print(f"错误发生:{e}")

三、正则表达式

使用条件

  • 非结构化数据:正则表达式适合处理纯文本或非结构化数据。

  • 模式匹配:当需要匹配特定模式的字符串时(如邮箱、URL、日期等)。

  • 复杂文本提取:适合从文本中提取符合特定规则的内容。

使用环境

  • 依赖库:Python内置的re模块。

  • 常见场景

    • 从日志文件中提取特定信息。

    • 验证字符串格式(如邮箱、电话号码)。

    • 处理非结构化文本数据。

优点

  • 强大的模式匹配能力,适合处理复杂文本。

  • 不依赖外部库,Python内置支持。

缺点

  • 语法复杂,学习曲线陡峭。

  • 对HTML/XML等结构化数据处理效率较低。

使用代码

import csv

try:
    for start_num in range(0, 250, 25):
        response = requests.get(f"https://movie.douban.com/top250?start={start_num}")
        if response.ok:
            page_content = response.text
            #解析数据
            obj = re.compile(r'<li>.*?<div class="item">.*?<span class="title">(?P<name>.*?)</span>'
                             r'.*?<p class="">.*?<br>(?P<year>.*?)&nbsp.*? <span class="rating_num" property="v:average">'
                             r'(?P<score>.*?)</span>.*?<span>(?P<review>.*?)</span>', re.S)
            result = obj.finditer(page_content)

            f = open("top250data.csv", mode="a")
            csvwriter = csv.writer(f)
            for it in result:
                # print(it.group("name"))
                # print(it.group("year").strip())
                # print(it.group("score"))
                # print(it.group("review"))
                dic = it.groupdict()
                dic['year'] = dic['year'].strip() # 单独处理
                csvwriter.writerow(dic.values())

            f.close()
            response.close()
            print("over!")
        else:
            print("请求失败")
except requests.RequestException as e:
    print(f"错误发生:{e}")

对比总结

特性XPathBeautifulSoup(bs4)正则表达式(Regex)
适用数据类型HTML/XML等结构化数据HTML/XML等结构化数据纯文本或非结构化数据
学习难度中等简单较难
性能中等
灵活性高(支持复杂路径和条件筛选)中等(适合简单提取)高(支持复杂模式匹配)
依赖库lxmlbs4 + 解析器(如lxmlPython内置re模块
适用场景复杂嵌套结构的数据提取快速提取简单数据文本模式匹配和提取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值