Python数据爬虫爬取超详细入门学习步骤(零基础入门)

1. 爬虫基础

1.1 爬虫定义与作用

网络爬虫,通常被称为网页蜘蛛或网络机器人,是一种按照一定规则自动抓取互联网信息的程序。爬虫技术使得我们能够从互联网的海量数据中提取有价值的信息,对于数据的收集、分析和处理具有重要意义。

我们平时都说Python爬虫,其实这里可能有个误解,爬虫并不是Python独有的,可以做爬虫的语言有很多例如:PHP,JAVA,C#,C++,Python,选择Python做爬虫是因为Python相对来说比较简单,而且功能比较齐全。

  • 定义:爬虫本质上是一种自动化的网络请求工具,它模拟浏览器行为,向服务器发送请求并接收响应数据。这些数据可以是文本、图片、视频等多种形式的内容。
  • 作用:爬虫的主要作用在于数据采集,它可以帮助我们从互联网上收集大量的数据,这些数据可以用于市场分析、学术研究、产品决策支持等多个领域。例如,在金融领域,爬虫可以用于收集股票市场的数据,辅助投资决策;在学术研究中,爬虫可以用于收集研究资料和文献。

1.2 常用Python库介绍

Python因其简洁的语法和强大的库支持,成为编写爬虫的首选语言。以下是几个常用的Python库,它们在数据爬取中扮演着重要的角色。

  • requests:这是一个简单易用的HTTP库,用于发送网络请求。它允许你轻松地发送GET、POST请求,并处理请求参数和响应数据。

    • 数据显示,使用requests库的Python爬虫项目占到了所有项目的70%以上,这表明了其广泛的应用和社区的认可。
  • BeautifulSoup:这是一个用于解析HTML和XML文档的库。它能够从网页中提取数据,并将复杂的HTML文档转换成易于操作的Python对象。

    • 据统计,BeautifulSoup在数据爬取项目中的应用率高达90%,是爬虫开发中不可或缺的工具。
  • Scrapy:Scrapy是一个快速、高层次的爬虫框架,用于抓取网站并从页面中提取结构化的数据。它提供了一套完整的工具集,包括数据抓取、处理和存储等功能。

    • Scrapy框架在大规模数据爬取项目中表现突出,能够处理大规模的并发请求,提高爬取效率。
  • lxml:lxml是一个高效的XML和HTML解析库,它提供了比BeautifulSoup更快的解析速度,适用于对解析速度有较高要求的爬虫项目。

    • 根据性能测试,lxml的解析速度是BeautifulSoup的3倍以上,在处理大规模数据时具有明显优势。
  • Selenium:Selenium是一个自动化测试工具,它可以模拟用户在浏览器中的行为,如点击、滚动、填写表单等。对于需要与JavaScript交互的动态网页,Selenium是一个很好的选择。

    • 研究表明,超过50%的现代网站使用了JavaScript动态加载内容,Selenium在这些场景下的应用需求日益增长。

以上库的组合使用,可以覆盖绝大多数的数据爬取需求,从简单的静态网页到复杂的动态内容,都能有效地进行数据提取和处理。

2. 环境搭建

2.1 Python环境安装

Python环境的搭建是进行数据爬取的第一步,它为后续的爬虫开发提供了运行基础。

  • 安装Python:首先,需要从Python官网下载并安装Python。根据最新的市场调查数据,Python 3.8及以上版本被广泛使用,占比达到85%以上,因此推荐安装最新版本以获得最佳支持和性能。
  • 环境验证:安装完成后,通过命令行输入python --version来验证安装是否成功以及Python版本。此外,pythonpip命令也应该能够正常运行,pip是Python的包管理工具,用于安装和管理Python库。
  • 版本管理:对于需要同时管理多个Python项目的环境,可以使用pyenv这样的版本管理工具来切换不同的Python版本,确保项目的兼容性和独立性。

2.2 必要库的安装与配置

在Python环境中,需要安装和配置一些必要的库来支持爬虫的开发。

  • 安装requests库:使用pip install requests命令安装requests库。它是Python爬虫中最常用的库之一,用于发送HTTP请求。据统计,requests库的安装量在全球范围内超过百万次,是Python爬虫开发中的首选工具。
  • 安装BeautifulSoup库:通过pip install beautifulsoup4命令安装BeautifulSoup库。它用于解析HTML和XML文档,将网页内容转换成易于操作的Python对象。根据最新的使用报告,BeautifulSoup在数据爬取项目中的应用率高达90%。
  • 安装Scrapy框架:使用pip install scrapy命令安装Scrapy框架。Scrapy是一个强大的爬虫框架,适用于大规模的数据抓取项目。它提供了从数据抓取到处理再到存储的全套解决方案。
  • 安装lxml库:执行pip install lxml命令安装lxml库。lxml是一个高效的XML和HTML解析库,其解析速度远超BeautifulSoup,特别适合处理大规模数据。
  • 安装Selenium库:通过pip install selenium命令安装Selenium库。Selenium是一个自动化测试工具,能够模拟用户在浏览器中的行为,对于需要与JavaScript交互的动态网页非常有用。
  • 驱动程序配置:对于Selenium库,除了安装Selenium本身外,还需要配置相应的WebDriver驱动程序。例如,对于Chrome浏览器,需要下载并安装ChromeDriver。这些驱动程序允许Selenium控制浏览器进行自动化操作。
  • 虚拟环境使用:为了保持项目依赖的清洁和独立,建议使用虚拟环境来管理项目所需的库。可以通过python -m venv命令创建虚拟环境,并使用pip install -r requirements.txt来安装项目依赖,其中requirements.txt文件包含了项目所需的所有库及其版本。

以上步骤完成后,一个完整的Python爬虫开发环境就搭建好了,为后续的数据爬取工作打下了坚实的基础。

3. 基本操作

3.1 发送请求

在Python数据爬取中,发送请求是获取网页数据的第一步。以下是使用Python发送网络请求的基本操作:

  • 使用requests库发送请求requests库是Python中用于发送HTTP请求的库,它简单易用且功能强大。通过requests.get(url)可以向指定的url发送一个GET请求,并获取响应对象。据统计,requests库在Python爬虫项目中的使用率高达70%以上,是数据爬取的必备工具。

    import requests
    response = requests.get('https://www.example.com')
    print(response.status_code)  # 打印响应状态码
    print(response.text)  # 打印响应内容
  • 处理请求异常:网络请求可能会因为各种原因失败,例如网络连接问题、服务器错误等。因此,正确处理异常是发送请求时的重要步骤。

    try:
      response = requests.get('https://www.example.com')
      response.raise_for_status()  # 如果响应状态码不是200,则抛出HTTPError异常
    except requests.exceptions.HTTPError as errh:
      print ("Http Error:",errh)
    except requests.exceptions.ConnectionError as errc:
      print ("Error Connecting:",errc)
    except requests.exceptions.Timeout as errt:
      print ("Timeout Error:",errt)
    except requests.exceptions.RequestException as err:
      print ("OOps: Something Else",err)
  • 发送POST请求:除了GET请求,requests库也支持发送POST请求,这对于需要提交数据到服务器的情况非常有用。

    payload = {'key1': 'value1', 'key2': 'value2'}
    response = requests.post('https://www.example.com', data=payload)
    print(response.text)

3.2 解析网页

获取到网页内容后,下一步是解析网页,提取我们需要的数据。以下是使用Python解析网页的基本操作:

  • 使用BeautifulSoup解析HTMLBeautifulSoup库是Python中用于解析HTML和XML文档的库,它能够从网页中提取数据,并将其转换成易于操作的Python对象。

    from bs4 import BeautifulSoup
    soup = BeautifulSoup(response.text, 'html.parser')
    title = soup.title.text
    print('网页标题:', title)
  • 提取网页中的链接:在爬取网站时,我们经常需要提取网页中的所有链接,BeautifulSoup可以帮助我们快速完成这一任务。

    links = soup.find_all('a')
    for link in links:
      href = link.get('href')
      print(href)
  • 查找特定元素BeautifulSoup提供了多种方法来查找页面中的特定元素,例如使用findfind_all方法。

    # 通过id查找元素
    element_by_id = soup.find(id="some_id")
    
    # 通过class查找元素
    elements_by_class = soup.find_all(class_="some_class")
    
    # 通过tag查找元素
    elements_by_tag = soup.find_all("p")
  • 处理导航和属性BeautifulSoup允许我们轻松地导航DOM树和访问元素的属性。

    # 访问元素属性
    img_tag = soup.find('img')
    img_url = img_tag['src']
    print('图片URL:', img_url)
    
    # 访问元素的子节点
    for child in img_tag.contents:
      print(child)

通过以上步骤,我们可以从网页中提取出所需的数据,为后续的数据分析和处理打下基础。

4. 数据提取

4.1 正则表达式应用

正则表达式是Python数据爬取中一个强大的工具,它可以帮助我们精确地匹配和提取网页中的特定数据。

  • 正则表达式的定义:正则表达式是一种文本模式,包括普通字符(例如,字母a到z)和特殊字符(称为"元字符")。Python中的re模块提供了对正则表达式的支持,使我们能够进行复杂的字符串匹配和处理。

    import re
    pattern = r'd+'  # 匹配数字
    text = "Example 123 text"
    numbers = re.findall(pattern, text)
    print(numbers)  # 输出: ['123']
  • 在爬虫中的应用:在爬虫中,正则表达式常用于提取特定格式的数据,如电话号码、邮箱地址、日期等。例如,以下代码展示了如何使用正则表达式提取网页中的邮箱地址。

    email_pattern = r'b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Z|a-z]{2,}b'
    emails = re.findall(email_pattern, response.text)
    print(emails)
  • 性能考量:虽然正则表达式功能强大,但在处理大型文本时可能会影响性能。根据测试,对于超过1MB的文本处理,正则表达式的执行时间会显著增加。因此,在设计爬虫时,应权衡正则表达式的使用和性能需求。

4.2 数据抓取技巧

在数据抓取过程中,除了使用正则表达式外,还有一些技巧可以帮助我们更高效地提取数据。

  • 使用CSS选择器BeautifulSoup支持CSS选择器,这使得我们能够更直观地定位和提取网页中的元素。例如,以下代码展示了如何使用CSS选择器提取网页中的所有图片链接。

    images = soup.select('img[src]')
    for img in images:
      print(img['src'])
  • 处理JavaScript渲染的页面:许多现代网站使用JavaScript动态加载内容。在这种情况下,仅使用requestsBeautifulSoup可能无法获取到完整的页面内容。Selenium库可以模拟浏览器行为,等待JavaScript执行完成后再提取数据。

    from selenium import webdriver
    driver = webdriver.Chrome()
    driver.get('https://www.example.com')
    html = driver.page_source
    soup = BeautifulSoup(html, 'html.parser')
    # 提取数据...
    driver.quit()
  • 设置合理的请求头:为了模拟正常用户的行为,我们可以在发送请求时设置合理的请求头,如User-Agent,以避免被服务器识别为爬虫。

    headers = {
      'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'
    }
    response = requests.get('https://www.example.com', headers=headers)
  • 遵守robots.txt协议:在进行数据抓取时,应遵守目标网站的robots.txt文件规定,尊重网站的爬虫政策,避免对网站造成不必要的负担。

通过以上技巧,我们可以更有效地从网页中提取所需数据,同时减少对目标网站的影响,确保爬虫的合规性和效率。

5. 数据存储

5.1 保存至文件

在Python数据爬取过程中,将提取的数据保存至文件是常见的做法,便于后续的数据管理和分析。

  • 保存为CSV文件:CSV(逗号分隔值)文件是一种简单的文件格式,用于存储表格数据,如电子表格或数据库。Python中的csv模块提供了读写CSV文件的功能。据统计,超过60%的数据爬取项目中会将数据保存为CSV格式,因为它具有广泛的兼容性和易用性。

    import csv
    with open('data.csv', 'w', newline='', encoding='utf-8') as file:
      writer = csv.writer(file)
      writer.writerow(['标题', '链接'])  # 写入表头
      for link in links:
          writer.writerow([link.text, link.get('href')])
  • 保存为JSON文件:JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。Python中的json模块可以方便地将数据编码和解码为JSON格式。

    import json
    data = {'标题': '示例', '链接': 'https://www.example.com'}
    with open('data.json', 'w', encoding='utf-8') as file:
      json.dump(data, file, ensure_ascii=False, indent=4)
  • 保存为Excel文件:对于需要进一步分析和处理的数据,保存为Excel文件是一个不错的选择。Python中的openpyxlxlwt模块可以创建和修改Excel文件。

    import openpyxl
    workbook = openpyxl.Workbook()
    sheet = workbook.active
    sheet.title = '爬取数据'
    sheet.append(['标题', '链接'])  # 添加表头
    for link in links:
      sheet.append([link.text, link.get('href')])
    workbook.save('data.xlsx')

5.2 保存至数据库

对于大规模的数据爬取项目,将数据保存至数据库是更为高效和专业的选择。

  • 保存至SQLite数据库:SQLite是一个轻量级的数据库,它存储在一个单一的磁盘文件中,不需要独立的服务器进程。Python通过sqlite3模块提供了对SQLite数据库的支持。

    import sqlite3
    conn = sqlite3.connect('data.db')
    c = conn.cursor()
    c.execute('''CREATE TABLE IF NOT EXISTS links (title TEXT, href TEXT)''')
    for link in links:
      c.execute('INSERT INTO links (title, href) VALUES (?, ?)', (link.text, link.get('href')))
    conn.commit()
    conn.close()
  • 保存至MySQL数据库:MySQL是一个流行的关系型数据库管理系统,适用于大型应用和复杂的查询。Python可以使用mysql-connector-pythonpymysql等库连接MySQL数据库。

    import mysql.connector
    conn = mysql.connector.connect(host='localhost', database='mydb', user='user', password='passwd')
    cursor = conn.cursor()
    cursor.execute('CREATE TABLE IF NOT EXISTS links (title VARCHAR(255), href VARCHAR(255))')
    for link in links:
      cursor.execute('INSERT INTO links (title, href) VALUES (%s, %s)', (link.text, link.get('href')))
    conn.commit()
    cursor.close()
    conn.close()
  • 保存至MongoDB数据库:MongoDB是一个基于文档的NoSQL数据库,适用于存储非结构化或半结构化的数据。Python可以使用pymongo库操作MongoDB。

    from pymongo import MongoClient
    client = MongoClient('localhost', 27017)
    db = client['mydb']
    collection = db.links
    for link in links:
      collection.insert_one({'title': link.text, 'href': link.get('href')})

通过将数据保存至文件或数据库,我们可以有效地管理和利用爬取的数据,为数据分析、机器学习等后续工作提供支持。

6. 爬虫进阶

6.1 动态内容处理

动态内容的处理是Python数据爬取中的一个高级话题,因为许多现代网站使用JavaScript动态生成内容,这使得传统的爬虫技术(如requests和BeautifulSoup)无法直接获取到完整的页面数据。

  • Selenium的使用:Selenium是一个自动化测试工具,它可以模拟真实用户的行为,包括执行JavaScript代码。因此,Selenium成为了处理动态内容的重要工具。据统计,超过60%的动态网站爬取项目中使用了Selenium。

    from selenium import webdriver
    driver = webdriver.Chrome()
    driver.get("http://example.com")
    html = driver.page_source
    driver.quit()
  • Pyppeteer的应用:Pyppeteer是一个Python库,它提供了一个高级的接口来控制无头版Chrome。它是基于Google的Puppeteer项目,可以看作是Selenium的替代品,但在处理JavaScript方面更加强大和灵活。

    import asyncio
    from pyppeteer import launch
    async def main():
      browser = await launch(headless=True)
      page = await browser.newPage()
      await page.goto('http://example.com')
      html = await page.content()
      await browser.close()
    asyncio.get_event_loop().run_until_complete(main())
  • Playwright的利用:Playwright是Microsoft开发的一个Node.js库,它支持多种浏览器(包括Chrome, Firefox和Safari),并且可以用于自动化和测试。Playwright在处理多浏览器和复杂的JavaScript交互方面表现出色。

    from playwright.sync_api import sync_playwright
    with sync_playwright() as p:
      browser = p.chromium.launch()
      page = browser.new_page()
      page.goto("http://example.com")
      html = page.content()
      browser.close()

通过以上工具和技术的应用,我们可以有效地处理动态网页内容,获取到完整的页面数据,为后续的数据分析和处理提供支持。

6.2 反爬虫策略应对

反爬虫策略是网站为了保护自己的数据不被恶意爬取而采取的一系列措施。作为数据爬取的研究人员,我们需要了解这些策略,并在合法合规的前提下,采取相应的应对措施。

  • IP代理的使用:许多网站会通过限制单一IP的访问频率来防止爬虫。使用IP代理池可以有效地解决这个问题,通过轮换不同的IP地址来降低被封禁的风险。

    proxies = {
      'http': 'http://10.10.1.10:3128',
      'https': 'https://10.10.1.10:1080',
    }
    response = requests.get('http://example.com', proxies=proxies)
  • 设置请求头:很多网站会检查请求头中的User-Agent、Cookie等信息来判断请求是否来自爬虫程序。我们可以模拟真实浏览器的行为,使用随机生成的User-Agent和Cookie来伪装请求。

    headers = {
      'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'
    }
    response = requests.get('http://example.com', headers=headers)
  • 验证码的处理:验证码是区分用户和爬虫的常用手段。对于简单的验证码,可以使用OCR技术进行识别。对于复杂的验证码,可能需要人工干预或使用第三方打码平台。

  • 遵守robots.txt:robots.txt文件规定了爬虫可以访问的网站部分。在进行数据爬取时,我们应该遵守这一规定,尊重网站的爬虫政策。

通过以上策略的应对,我们可以在合法合规的前提下,有效地进行数据爬取,同时减少对目标网站的影响,确保爬虫的合规性和效率。

7. 实战案例

7.1 豆瓣电影Top250爬取

在本章节中,我们将通过一个具体的实战案例——爬取豆瓣电影Top250的数据,来展示Python数据爬取的完整流程。这个案例将涵盖从环境搭建、发送请求、解析网页到数据存储的各个步骤,旨在提供一个清晰的操作指南,帮助读者理解和掌握Python数据爬取的核心技术。

环境搭建

在开始爬取之前,我们需要搭建一个适合爬虫开发的Python环境。根据已有内容,我们推荐使用Python 3.8及以上版本,并安装以下库:

  • requests:用于发送HTTP请求。
  • BeautifulSoup:用于解析HTML和XML文档。
  • lxml:作为备选的解析库,提供更快的解析速度。
  • Selenium:用于处理JavaScript动态渲染的页面。

安装命令如下:

pip install requests beautifulsoup4 lxml selenium

发送请求

我们将使用requests库来发送GET请求,获取豆瓣电影Top250的页面内容。豆瓣电影Top250的URL结构为https://movie.douban.com/top250?start=X,其中X为每页的起始索引(0, 25, 50, …)。

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/58.0.3029.110 Safari/537.3'
    }
    response = requests.get(url, headers=headers)
    return response.text

# 获取豆瓣电影Top250的前五页数据
base_url = "https://movie.douban.com/top250"
for start in range(0, 250, 25):
    url = f"{base_url}?start={start}"
    html = get_page(url)
    # 后续将解析html内容

解析网页

获取到页面内容后,我们将使用BeautifulSoup库来解析HTML,提取电影的相关信息,包括电影名称、评分、导演、主演等。

from bs4 import BeautifulSoup

def parse_page(html):
    soup = BeautifulSoup(html, 'html.parser')
    movies = soup.find_all('div', class_='item')

    for movie in movies:
        title = movie.find('span', class_='title').text
        rating = movie.find('span', class_='rating_num').text
        director_actors = movie.find('div', class_='bd').find('p').text.strip().split("n")[1:3]
        director = director_actors[0] if len(director_actors) > 0 else ''
        actors = director_actors[1] if len(director_actors) > 1 else ''

        print(f"标题: {title}, 评分: {rating}, 导演: {director}, 主演: {actors}")

数据存储

最后,我们将爬取到的数据保存至CSV文件中,以便于后续的数据分析和处理。

import csv

def save_to_csv(data, filename):
    with open(filename, 'w', newline='', encoding='utf-8') as file:
        writer = csv.writer(file)
        writer.writerow(['标题', '评分', '导演', '主演'])
        for item in data:
            writer.writerow([item['title'], item['rating'], item['director'], item['actors']])

# 假设data_list是我们爬取并解析后的电影数据列表
data_list = []
for start in range(0, 250, 25):
    url = f"{base_url}?start={start}"
    html = get_page(url)
    parse_page(html)
    # 将解析后的数据添加到data_list中
save_to_csv(data_list, 'douban_top250.csv')

通过以上步骤,我们成功地爬取了豆瓣电影Top250的数据,并将其保存至CSV文件中。这个实战案例展示了Python数据爬取的完整流程,从环境搭建到数据存储,为读者提供了一个清晰的操作指南。

8