【Python爬虫详解】第三篇:编写你的第一个爬虫程序

在前两篇文章中,我们介绍了网络爬虫的基本概念和HTML的结构。有了这些基础知识,现在我们可以开始编写自己的第一个爬虫程序了。本文将带你一步步了解爬虫程序的基本结构、必要的组件以及一个简单实用的爬虫模板,帮助你快速入门爬虫开发。

一、爬虫程序的基本流程

一个典型的爬虫程序通常包含以下几个步骤:

  1. 发送HTTP请求:向目标网站发送请求获取网页内容
  2. 接收服务器响应:接收并处理服务器返回的数据
  3. 解析HTML内容:从响应中提取出HTML,并进行解析
  4. 提取有用数据:从解析后的HTML中提取需要的信息
  5. 数据存储:将提取的数据保存到文件或数据库中

图片

二、准备工作:安装必要的库

在开始编写爬虫之前,我们需要安装最基本的爬虫库——Requests。它是Python中最流行的HTTP库,设计简洁且功能强大,非常适合初学者。

pip install requests

如果你已经安装了Python,可以直接在命令行中运行上面的命令来安装Requests库。

三、最简单的爬虫示例

让我们从最简单的例子开始,爬取一个网页并打印其内容:

import requests

# 发送GET请求获取网页内容
url = "https://www.example.com"
response = requests.get(url)

# 检查请求是否成功
if response.status_code == 200:
    # 输出网页内容
    print(response.text)
else:
    print(f"请求失败,状态码:{response.status_code}")

这段代码的工作流程是:

  1. 导入requests库
  2. 定义目标URL
  3. 使用requests.get()方法发送GET请求
  4. 检查响应状态码是否为200(表示请求成功)
  5. 如果成功,打印网页内容;否则,打印错误信息

四、HTTP请求头与Cookie

在实际爬取过程中,很多网站会检查请求头信息,特别是User-Agent(用户代理),以确定请求来源。如果不设置适当的请求头,网站可能会拒绝我们的请求或返回不同的内容。

1. 添加请求头(Headers)

import requests

url = "https://www.example.com"

# 定义请求头
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",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
    "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8"
}

# 发送带有请求头的GET请求
response = requests.get(url, headers=headers)

if response.status_code == 200:
    print("请求成功!")
    # 仅打印内容前100个字符
    print(response.text[:100] + "...")
else:
    print(f"请求失败,状态码:{response.status_code}")

常用的请求头字段及其作用:

  • User-Agent:标识请求的浏览器类型和操作系统信息
  • Accept:指定客户端能够接收的内容类型
  • Accept-Language:指定客户端能够接收的语言
  • Referer:指定请求来源页面的URL,有些网站会验证这个字段
  • Connection:指定与服务器的连接类型(如keep-alive或close)

2. 使用Cookie

有些网站需要Cookie来维持会话状态或验证身份。以下是使用Cookie的简单示例:

import requests

url = "https://www.example.com/user-profile"

# 手动设置Cookie
cookies = {
    "session_id": "abc123",
    "user_token": "xyz789"
}

# 方法1:在请求中直接传入cookies参数
response = requests.get(url, cookies=cookies)

# 方法2:创建会话对象并设置Cookie
session = requests.Session()
session.cookies.update(cookies)
response = session.get(url)

print(response.text[:100] + "...")

3. 使用会话(Session)保持状态

如果需要在多个请求之间保持状态(如登录会话),可以使用Session对象:

import requests

# 创建会话对象
session = requests.Session()

# 设置会话级别的请求头
session.headers.update({
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/91.0.4472.124"
})

# 登录
login_url = "https://www.example.com/login"
login_data = {
    "username": "your_username",
    "password": "your_password"
}
login_response = session.post(login_url, data=login_data)

# 使用同一会话访问需要登录的页面
profile_url = "https://www.example.com/profile"
profile_response = session.get(profile_url)

print(profile_response.text[:100] + "...")

五、处理不同类型的请求

1. GET请求(获取数据)

GET请求通常用于从服务器获取数据,可以通过URL参数传递数据:

import requests

# 不带参数的GET请求
response = requests.get("https://www.example.com")

# 带参数的GET请求
params = {
    "q": "python爬虫",
    "page": 1
}
response = requests.get("https://www.example.com/search", params=params)

# 上面的请求等同于访问:https://www.example.com/search?q=python爬虫&page=1
print(response.url)  # 打印完整URL

2. POST请求(提交数据)

POST请求通常用于向服务器提交数据,如表单提交:

import requests

# 提交表单数据
form_data = {
    "username": "test_user",
    "email": "test@example.com",
    "message": "Hello World!"
}

response = requests.post("https://www.example.com/submit", data=form_data)
print(response.text)

# 提交JSON数据
json_data = {
    "name": "Test Product",
    "price": 99.99,
    "available": True
}

response = requests.post("https://www.example.com/api/products", json=json_data)
print(response.json())  # 如果响应是JSON格式,可以直接解析

六、一个实用的爬虫模板

下面是一个实用的爬虫模板,包含了基本的错误处理和重试机制:

import requests
import time
import random
import logging
from requests.exceptions import RequestException

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s: %(message)s'
)

def fetch_page(url, headers=None, cookies=None, max_retries=3, timeout=10):
    """
    获取网页内容的函数,包含重试机制
    
    参数:
        url (str): 要爬取的URL
        headers (dict): 请求头
        cookies (dict): Cookie
        max_retries (int): 最大重试次数
        timeout (int): 请求超时时间(秒)
        
    返回:
        response对象 或 None(如果请求失败)
    """
    # 默认请求头
    if headers is None:
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/91.0.4472.124 Safari/537.36',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
            'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
        }
    
    # 重试机制
    for attempt in range(max_retries):
        try:
            logging.info(f"正在获取页面: {url}")
            response = requests.get(
                url, 
                headers=headers, 
                cookies=cookies,
                timeout=timeout
            )
            
            # 检查响应状态
            if response.status_code == 200:
                return response
            else:
                logging.warning(f"请求失败,状态码: {response.status_code}")
                
        except RequestException as e:
            logging.error(f"请求异常: {e}")
        
        # 如果不是最后一次重试,则等待后继续
        if attempt < max_retries - 1:
            # 随机等待1-3秒
            sleep_time = 1 + random.random() * 2
            logging.info(f"等待 {sleep_time:.1f} 秒后重试...")
            time.sleep(sleep_time)
    
    logging.error(f"已达到最大重试次数 {max_retries},获取页面失败")
    return None

def save_to_file(content, filename):
    """保存内容到文件"""
    try:
        with open(filename, 'w', encoding='utf-8') as f:
            f.write(content)
        logging.info(f"内容已保存到文件: {filename}")
        return True
    except Exception as e:
        logging.error(f"保存文件时出错: {e}")
        return False

def main():
    # 目标网页URL
    url = "https://www.example.com"
    
    # 获取页面内容
    response = fetch_page(url)
    
    if response:
        # 保存页面内容
        save_to_file(response.text, "example_page.html")
        
        # 这里可以添加解析页面内容的代码
        # 在下一篇文章中我们将使用解析库来提取数据
        
        logging.info("爬取任务完成")
    else:
        logging.error("爬取失败")

if __name__ == "__main__":
    main()

这个模板包含:

  • 基本的请求发送函数,带有重试机制
  • 错误处理和日志记录
  • 随机延迟,避免请求过于频繁
  • 文件保存功能
  • 主函数结构

七、常见问题与解决方案

1. 请求被拒绝(403 Forbidden)

可能原因:网站检测到爬虫行为或缺少必要的请求头。

解决方案

  • 添加或修改User-Agent等请求头
  • 降低请求频率,添加随机延迟
  • 使用代理IP(进阶方法,本文不详述)

2. 超时错误

可能原因:网络连接不稳定或服务器响应慢。

解决方案

  • 增加超时时间
  • 实现重试机制
  • 检查网络连接

3. 网站需要登录

可能原因:内容只对已登录用户可见。

解决方案

  • 使用Session对象和模拟登录
  • 手动获取并设置Cookie

八、实际案例:爬取百度热搜榜

最后,让我们用一个实际案例来展示如何使用上述知识爬取百度热搜榜:

import requests
import time
import logging

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s: %(message)s')

def get_baidu_hot_search():
    """获取百度热搜榜"""
    url = "https://top.baidu.com/board?tab=realtime"
    
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/91.0.4472.124 Safari/537.36",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
        "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8"
    }
    
    try:
        logging.info("开始获取百度热搜榜...")
        response = requests.get(url, headers=headers, timeout=10)
        
        if response.status_code == 200:
            logging.info("获取成功!")
            
            # 将响应内容保存到文件中
            with open("baidu_hot_search.html", "w", encoding="utf-8") as f:
                f.write(response.text)
            logging.info("已保存热搜页面HTML到baidu_hot_search.html")
            
            return response.text
        else:
            logging.error(f"请求失败,状态码:{response.status_code}")
            return None
            
    except Exception as e:
        logging.error(f"获取百度热搜时出错: {e}")
        return None

if __name__ == "__main__":
    content = get_baidu_hot_search()
    
    if content:
        logging.info("爬取完成!在下一篇文章中,我们将学习如何解析这个页面的HTML内容并提取热搜榜数据。")
    else:
        logging.error("爬取失败!")

这个案例展示了如何使用请求头来模拟浏览器访问百度热搜榜,并将获取到的HTML内容保存到文件中。在下一篇文章中,我们将学习如何使用解析库(如BeautifulSoup)来提取这个HTML中的热搜榜数据。

九、总结与注意事项

本文介绍了编写第一个爬虫程序的基本步骤:

  1. 准备环境:安装requests库
  2. 发送请求:使用GET或POST方法获取网页内容
  3. 设置请求头和Cookie:模拟真实浏览器行为
  4. 错误处理与重试:处理可能出现的网络问题
  5. 保存数据:将获取的内容保存到文件中

在编写爬虫时,需要注意以下几点:

  • 尊重网站规则:查看并遵守robots.txt文件
  • 控制请求频率:避免频繁请求对服务器造成负担
  • 异常处理:妥善处理可能出现的各种错误
  • 模拟真实用户:设置合理的请求头和Cookie
  • 代码可维护性:编写清晰、结构化的代码

通过本文的学习,你应该已经掌握了编写一个基本爬虫的方法。在下一篇文章中,我们将介绍如何使用BeautifulSoup等解析库,从HTML中提取所需的数据。


下一篇:【Python爬虫详解】第四篇:使用解析库提取网页数据

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Luck_ff0810

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值