首页 > 编程语言 >Python爬虫大详解,助你成为大佬

Python爬虫大详解,助你成为大佬

时间:2024-10-24 22:46:46浏览次数:3  
标签:Python text 爬虫 element 详解 print import requests response

基础知识

Python基础:熟悉Python语言的基本语法,包括变量、数据类型(字符串、列表、字典等)、条件语句、循环、函数定义等

1. 变量

在Python中,变量不需要声明类型,直接赋值即可。

x = 10          # 整数
y = 3.14        # 浮点数
name = "Alice"  # 字符串
is_student = True  # 布尔值

2. 数据类型

基本数据类型
  • 整数 (int):表示整数值。
  • 浮点数 (float):表示小数值。
  • 字符串 (str):表示文本。
  • 布尔值 (bool):表示真 (True) 或假 (False)。
age = 25
height = 5.9
name = "John Doe"
is_active = False
复合数据类型
  • 列表 (list):有序的可变集合。
  • 元组 (tuple):有序的不可变集合。
  • 字典 (dict):无序的键值对集合。
  • 集合 (set):无序且不重复的元素集合。
# 列表
fruits = ["apple", "banana", "cherry"]

# 元组
coordinates = (10, 20)

# 字典
person = {"name": "Alice", "age": 25, "city": "New York"}

# 集合
unique_numbers = {1, 2, 3, 4, 5}

3. 条件语句

条件语句用于根据不同的条件执行不同的代码块。

age = 20

if age < 18:
    print("未成年")
elif age >= 18 and age < 60:
    print("成年")
else:
    print("老年")

4. 循环

循环用于重复执行某段代码。

for 循环
# 遍历列表
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
    print(fruit)

# 使用range函数
for i in range(5):  # 0到4
    print(i)
while 循环
count = 0
while count < 5:
    print(count)
    count += 1

5. 函数定义

函数用于封装一段可重用的代码。

def greet(name):
    return f"Hello, {name}!"

print(greet("Alice"))

# 带默认参数的函数
def greet_with_default(name="Guest"):
    return f"Hello, {name}!"

print(greet_with_default())
print(greet_with_default("Bob"))

6. 列表推导式

列表推导式是一种简洁的创建列表的方法。

squares = [x**2 for x in range(10)]
print(squares)  # 输出: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

7. 字典推导式

字典推导式用于创建字典。

squares_dict = {x: x**2 for x in range(5)}
print(squares_dict)  # 输出: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

8. 文件操作

读写文件是常见的操作。

# 写入文件
with open("example.txt", "w") as file:
    file.write("Hello, World!")

# 读取文件
with open("example.txt", "r") as file:
    content = file.read()
    print(content)

9. 异常处理

异常处理用于捕获和处理运行时错误。

try:
    result = 10 / 0
except ZeroDivisionError:
    print("除零错误")
finally:
    print("无论是否发生异常,都会执行这里")

10. 模块导入

模块导入用于使用其他文件中的代码。

import math

print(math.sqrt(16))  # 输出: 4.0

# 导入特定函数
from math import sqrt

print(sqrt(16))  # 输出: 4.0

2、网络请求:了解HTTP协议的基础知识,包括GET和POST请求,以及如何使用Python发送这些请求。

HTTP协议基础

1. HTTP协议

HTTP(HyperText Transfer Protocol)是用于从Web服务器传输超文本到本地浏览器的传输协议。它是一个应用层协议,基于客户端-服务器模型。

2. 请求方法

HTTP协议定义了多种请求方法,其中最常用的是GET和POST:

  • GET:用于请求指定的资源。GET请求应该只用于获取数据,而不应该用于修改服务器上的数据。GET请求的参数通常附加在URL后面。
  • POST:用于向指定资源提交数据,通常用于提交表单数据或上传文件。POST请求的参数放在请求体中。
3. 请求和响应
  • 请求:客户端(如浏览器)向服务器发送的请求,包含请求行、请求头和请求体。
  • 响应:服务器返回给客户端的响应,包含状态行、响应头和响应体。

使用Python发送HTTP请求

1. 使用requests

requests库是Python中最常用的HTTP库之一,简单易用且功能强大。首先需要安装requests库:

pip install requests
2. 发送GET请求

发送GET请求非常简单,只需要调用requests.get()方法。

import requests

# 发送GET请求
response = requests.get('https://api.example.com/data')

# 检查请求是否成功
if response.status_code == 200:
    # 打印响应内容
    print(response.text)
else:
    print(f"请求失败,状态码: {response.status_code}")
3. 发送带参数的GET请求

可以在URL后面附加查询参数,或者使用params参数传递字典。

import requests

# 定义查询参数
params = {
    'key1': 'value1',
    'key2': 'value2'
}

# 发送GET请求
response = requests.get('https://api.example.com/data', params=params)

# 检查请求是否成功
if response.status_code == 200:
    # 打印响应内容
    print(response.text)
else:
    print(f"请求失败,状态码: {response.status_code}")
4. 发送POST请求

发送POST请求时,通常需要在请求体中包含数据。可以使用data参数传递字典。

import requests

# 定义请求体数据
data = {
    'username': 'user123',
    'password': 'pass456'
}

# 发送POST请求
response = requests.post('https://api.example.com/login', data=data)

# 检查请求是否成功
if response.status_code == 200:
    # 打印响应内容
    print(response.text)
else:
    print(f"请求失败,状态码: {response.status_code}")
5. 处理响应

requests库提供了多种方法来处理响应,包括获取响应状态码、响应头和响应体。

import requests

# 发送GET请求
response = requests.get('https://api.example.com/data')

# 获取状态码
status_code = response.status_code
print(f"状态码: {status_code}")

# 获取响应头
headers = response.headers
print(f"响应头: {headers}")

# 获取响应体
text = response.text
json_data = response.json()  # 如果响应内容是JSON格式

print(f"响应内容: {text}")
print(f"JSON数据: {json_data}")

3、HTML/CSS:理解网页的结构,知道如何通过标签和CSS选择器定位页面元素。

1. HTML (HyperText Markup Language)

1.1 基本结构

HTML 是一种标记语言,用于创建网页。一个基本的HTML文档结构如下:

<!DOCTYPE html>
<html>
<head>
    <title>网页标题</title>
</head>
<body>
    <h1>主标题</h1>
    <p>这是一个段落。</p>
    <a href="https://example.com">链接</a>
    <img src="image.jpg" alt="描述">
</body>
</html>
1.2 常见标签
  • <html>:文档根元素。
  • <head>:包含文档的元数据,如标题、样式表链接等。
  • <title>:文档的标题。
  • <body>:文档的主体内容。
  • <h1> 到 <h6>:标题标签,<h1> 是最大的标题,<h6> 是最小的标题。
  • <p>:段落标签。
  • <a>:超链接标签,href 属性指定链接的目标。
  • <img>:图像标签,src 属性指定图像的URL,alt 属性提供替代文本。
  • <div>:块级容器,用于分组和布局。
  • <span>:内联容器,用于文本格式化。

2. CSS (Cascading Style Sheets)

2.1 基本概念

CSS 用于控制网页的样式和布局。通过CSS,可以改变字体、颜色、间距、边框等。

2.2 选择器

选择器用于选择要应用样式的HTML元素。常见的选择器包括:

  • 标签选择器:选择特定的HTML标签。

    p {
        color: blue;
    }
  • 类选择器:选择具有特定类名的元素。

    .highlight {
        background-color: yellow;
    }
  • ID选择器:选择具有特定ID的元素。

    #header {
        font-size: 24px;
    }
  • 属性选择器:选择具有特定属性的元素。

    a[target="_blank"] {
        color: green;
    }
  • 伪类选择器:选择具有特定状态的元素。

    a:hover {
        text-decoration: underline;
    }
  • 组合选择器:组合多个选择器以选择更具体的元素。

    div p {
        color: red;
    }

3. 在爬虫中的应用

3.1 解析HTML

使用Python库如BeautifulSouplxml来解析HTML文档并提取所需数据。

示例:使用BeautifulSoup解析HTML
from bs4 import BeautifulSoup
import requests

# 发送HTTP请求获取网页内容
url = 'https://example.com'
response = requests.get(url)
html_content = response.text

# 使用BeautifulSoup解析HTML
soup = BeautifulSoup(html_content, 'html.parser')

# 提取标题
title = soup.title.string
print(f"标题: {title}")

# 提取所有段落
paragraphs = soup.find_all('p')
for p in paragraphs:
    print(p.text)

# 提取带有特定类名的元素
highlighted_elements = soup.find_all(class_='highlight')
for element in highlighted_elements:
    print(element.text)

# 提取带有特定ID的元素
header_element = soup.find(id='header')
print(header_element.text)

# 提取带有特定属性的元素
external_links = soup.find_all('a', target='_blank')
for link in external_links:
    print(link['href'])
3.2 使用CSS选择器

BeautifulSouplxml都支持使用CSS选择器来定位元素。

示例:使用CSS选择器
from bs4 import BeautifulSoup
import requests

# 发送HTTP请求获取网页内容
url = 'https://example.com'
response = requests.get(url)
html_content = response.text

# 使用BeautifulSoup解析HTML
soup = BeautifulSoup(html_content, 'html.parser')

# 使用CSS选择器提取标题
title = soup.select_one('title').string
print(f"标题: {title}")

# 提取所有段落
paragraphs = soup.select('p')
for p in paragraphs:
    print(p.text)

# 提取带有特定类名的元素
highlighted_elements = soup.select('.highlight')
for element in highlighted_elements:
    print(element.text)

# 提取带有特定ID的元素
header_element = soup.select_one('#header')
print(header_element.text)

# 提取带有特定属性的元素
external_links = soup.select('a[target="_blank"]')
for link in external_links:
    print(link['href'])

Python库

1、python官网:PyPI · The Python Package Index

2、知乎对python的库的讲解:https://zhuanlan.zhihu.com/p/89477028

Requests库:用于发送网络请求,获取网页内容。

1. 安装 requests 库

首先,你需要安装 requests 库。可以通过 pip 命令来安装:

pip install requests

2. 发送 GET 请求

发送 GET 请求是最常见的操作之一,用于从服务器获取数据。

基本用法
import requests

# 发送GET请求
response = requests.get('https://api.example.com/data')

# 检查请求是否成功
if response.status_code == 200:
    # 打印响应内容
    print(response.text)
else:
    print(f"请求失败,状态码: {response.status_code}")
带参数的 GET 请求

你可以在 URL 后面附加查询参数,或者使用 params 参数传递字典。

import requests

# 定义查询参数
params = {
    'key1': 'value1',
    'key2': 'value2'
}

# 发送GET请求
response = requests.get('https://api.example.com/data', params=params)

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

3. 发送 POST 请求

发送 POST 请求通常用于向服务器提交数据,例如表单数据或文件上传。

基本用法
import requests

# 定义请求体数据
data = {
    'username': 'user123',
    'password': 'pass456'
}

# 发送POST请求
response = requests.post('https://api.example.com/login', data=data)

# 检查请求是否成功
if response.status_code == 200:
    # 打印响应内容
    print(response.text)
else:
    print(f"请求失败,状态码: {response.status_code}")
发送 JSON 数据

如果需要发送 JSON 格式的数据,可以使用 json 参数。

import requests

# 定义请求体数据
data = {
    'username': 'user123',
    'password': 'pass456'
}

# 发送POST请求
response = requests.post('https://api.example.com/login', json=data)

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

4. 处理响应

requests 库提供了多种方法来处理响应,包括获取响应状态码、响应头和响应体。

获取状态码
import requests

response = requests.get('https://api.example.com/data')
status_code = response.status_code
print(f"状态码: {status_code}")
获取响应头
import requests

response = requests.get('https://api.example.com/data')
headers = response.headers
print(f"响应头: {headers}")
获取响应体
import requests

response = requests.get('https://api.example.com/data')
text = response.text  # 获取响应内容的文本形式
json_data = response.json()  # 如果响应内容是JSON格式

print(f"响应内容: {text}")
print(f"JSON数据: {json_data}")

5. 高级用法

设置请求头

有时候需要设置请求头,例如设置 User-AgentContent-Type

import requests

headers = {
    'User-Agent': 'MyApp/1.0',
    'Content-Type': 'application/json'
}

response = requests.get('https://api.example.com/data', headers=headers)
print(response.text)
设置超时

可以通过 timeout 参数设置请求的超时时间(单位为秒)。

import requests

response = requests.get('https://api.example.com/data', timeout=5)
print(response.text)
处理 cookies

可以使用 cookies 参数发送 cookies,或者从响应中获取 cookies。

import requests

# 发送带有cookies的请求
cookies = {'session_id': '12345'}
response = requests.get('https://api.example.com/data', cookies=cookies)
print(response.text)

# 从响应中获取cookies
cookies = response.cookies
print(cookies)
会话对象

使用 Session 对象可以保持会话状态,例如保持 cookies。

import requests

# 创建一个Session对象
session = requests.Session()

# 发送第一个请求
response1 = session.get('https://api.example.com/login', data={'username': 'user123', 'password': 'pass456'})
print(response1.text)

# 发送第二个请求,会话状态保持
response2 = session.get('https://api.example.com/dashboard')
print(response2.text)

BeautifulSoup库:解析HTML文档,提取所需信息。

1. 安装 BeautifulSoup 库

首先,你需要安装 BeautifulSoup 库。可以通过 pip 命令来安装:

pip install beautifulsoup4

2. 基本用法

2.1 创建 BeautifulSoup 对象

首先,你需要从 bs4 模块中导入 BeautifulSoup 类,并创建一个 BeautifulSoup 对象。

from bs4 import BeautifulSoup
import requests

# 发送HTTP请求获取网页内容
url = 'https://example.com'
response = requests.get(url)
html_content = response.text

# 创建BeautifulSoup对象
soup = BeautifulSoup(html_content, 'html.parser')

3. 解析 HTML 文档

3.1 提取标题
# 提取标题
title = soup.title.string
print(f"标题: {title}")
3.2 提取所有段落
# 提取所有段落
paragraphs = soup.find_all('p')
for p in paragraphs:
    print(p.text)
3.3 提取带有特定类名的元素
# 提取带有特定类名的元素
highlighted_elements = soup.find_all(class_='highlight')
for element in highlighted_elements:
    print(element.text)
3.4 提取带有特定 ID 的元素
# 提取带有特定ID的元素
header_element = soup.find(id='header')
print(header_element.text)
3.5 提取带有特定属性的元素
# 提取带有特定属性的元素
external_links = soup.find_all('a', target='_blank')
for link in external_links:
    print(link['href'])

4. 使用 CSS 选择器

BeautifulSoup 支持使用 CSS 选择器来定位元素,这使得提取信息更加灵活和方便。

4.1 提取标题
# 提取标题
title = soup.select_one('title').string
print(f"标题: {title}")
4.2 提取所有段落
# 提取所有段落
paragraphs = soup.select('p')
for p in paragraphs:
    print(p.text)
4.3 提取带有特定类名的元素
# 提取带有特定类名的元素
highlighted_elements = soup.select('.highlight')
for element in highlighted_elements:
    print(element.text)
4.4 提取带有特定 ID 的元素
# 提取带有特定ID的元素
header_element = soup.select_one('#header')
print(header_element.text)
4.5 提取带有特定属性的元素
# 提取带有特定属性的元素
external_links = soup.select('a[target="_blank"]')
for link in external_links:
    print(link['href'])

5. 处理嵌套结构

有时需要处理嵌套的 HTML 结构,BeautifulSoup 提供了多种方法来遍历和处理这些结构。

5.1 遍历子节点
# 遍历子节点
for child in header_element.children:
    print(child)
5.2 遍历兄弟节点
# 遍历兄弟节点
for sibling in header_element.next_siblings:
    print(sibling)

6. 处理特殊字符

HTML 文档中可能会包含特殊字符,BeautifulSoup 会自动处理这些字符。

# 提取包含特殊字符的文本
special_text = soup.find('p', class_='special').text
print(special_text)

7. 处理注释

HTML 文档中可能会包含注释,BeautifulSoup 也提供了处理注释的方法。

# 提取注释
for comment in soup.find_all(string=lambda text: isinstance(text, Comment)):
    print(comment)

lxml库:提供快速的XML和HTML处理功能,也可以用于解析网页。

1. 安装 lxml 库

首先,你需要安装 lxml 库。可以通过 pip 命令来安装:

pip install lxml

2. 基本用法

2.1 创建 ElementTree 对象

lxml 使用 ElementTree API 来解析和操作 XML 和 HTML 文档。首先,你需要从 lxml.etree 模块中导入相关类,并创建一个 ElementTree 对象。

from lxml import etree
import requests

# 发送HTTP请求获取网页内容
url = 'https://example.com'
response = requests.get(url)
html_content = response.text

# 解析HTML文档
tree = etree.HTML(html_content)

3. 解析 HTML 文档

3.1 提取标题
# 提取标题
title = tree.xpath('//title/text()')[0]
print(f"标题: {title}")
3.2 提取所有段落
# 提取所有段落
paragraphs = tree.xpath('//p/text()')
for p in paragraphs:
    print(p)
3.3 提取带有特定类名的元素
# 提取带有特定类名的元素
highlighted_elements = tree.xpath('//p[@class="highlight"]/text()')
for element in highlighted_elements:
    print(element)
3.4 提取带有特定 ID 的元素
# 提取带有特定ID的元素
header_element = tree.xpath('//div[@id="header"]/text()')[0]
print(header_element)
3.5 提取带有特定属性的元素
# 提取带有特定属性的元素
external_links = tree.xpath('//a[@target="_blank"]/@href')
for link in external_links:
    print(link)

4. 使用 XPath 表达式

XPath 是一种在 XML 文档中查找信息的语言,lxml 支持使用 XPath 表达式来定位和提取元素。

4.1 提取多级嵌套的元素
# 提取多级嵌套的元素
nested_elements = tree.xpath('//div[@class="container"]/p[@class="highlight"]/text()')
for element in nested_elements:
    print(element)
4.2 提取包含特定文本的元素
# 提取包含特定文本的元素
elements_with_text = tree.xpath('//p[contains(text(), "特定文本")]/text()')
for element in elements_with_text:
    print(element)

5. 处理特殊字符

HTML 文档中可能会包含特殊字符,lxml 会自动处理这些字符。

# 提取包含特殊字符的文本
special_text = tree.xpath('//p[@class="special"]/text()')[0]
print(special_text)

6. 处理注释

HTML 文档中可能会包含注释,lxml 也提供了处理注释的方法。

# 提取注释
comments = tree.xpath('//comment()')
for comment in comments:
    print(comment)

7. 处理命名空间

在处理包含命名空间的 XML 文档时,需要特别注意命名空间的处理。

# 解析包含命名空间的XML文档
xml_content = '''
<root xmlns:ns="http://example.com/ns">
    <ns:item id="1">Item 1</ns:item>
    <ns:item id="2">Item 2</ns:item>
</root>
'''

# 解析XML文档
tree = etree.fromstring(xml_content)

# 提取命名空间下的元素
items = tree.xpath('//ns:item/text()', namespaces={'ns': 'http://example.com/ns'})
for item in items:
    print(item)

8. 处理 HTML 错误

lxml 可以处理不标准的 HTML 文档,自动修复一些常见的错误。

# 解析不标准的HTML文档
html_content = '<html><body><p>未闭合的标签</p>'
tree = etree.HTML(html_content)

# 提取段落
paragraphs = tree.xpath('//p/text()')
for p in paragraphs:
    print(p)

Scrapy框架:一个强大的爬虫框架,适用于大规模的数据抓取项目。

1. 安装 Scrapy 框架

首先,你需要安装 Scrapy 框架。可以通过 pip 命令来安装

pip install scrapy

2. 创建 Scrapy 项目

使用 scrapy startproject 命令创建一个新的 Scrapy 项目。

scrapy startproject myproject

这将创建一个名为 myproject 的目录,包含以下文件和目录结构:

myproject/
    scrapy.cfg            # 部署配置文件
    myproject/            # Python 包
        __init__.py       # 初始化文件
        items.py          # 定义数据项
        middlewares.py    # 中间件
        pipelines.py      # 数据管道
        settings.py       # 项目设置
        spiders/          # 爬虫文件夹
            __init__.py
            spider1.py    # 爬虫文件

3. 编写爬虫

3.1 创建爬虫

spiders 目录下创建一个新的爬虫文件,例如 spider1.py

import scrapy

class MySpider(scrapy.Spider):
    name = 'myspider'  # 爬虫名称
    allowed_domains = ['example.com']  # 允许的域名
    start_urls = ['https://example.com']  # 起始URL

    def parse(self, response):
        # 解析响应内容
        title = response.xpath('//title/text()').get()
        print(f"标题: {title}")

        # 提取所有段落
        paragraphs = response.xpath('//p/text()').getall()
        for p in paragraphs:
            print(p)

        # 继续请求其他页面
        next_page = response.xpath('//a[@class="next"]/@href').get()
        if next_page:
            yield response.follow(next_page, self.parse)
3.2 运行爬虫

在项目根目录下运行爬虫:

scrapy crawl myspider

4. 定义数据项

items.py 文件中定义数据项,用于存储抓取的数据。

import scrapy

class MyItem(scrapy.Item):
    title = scrapy.Field()
    content = scrapy.Field()
    url = scrapy.Field()

5. 数据提取

在爬虫中使用 XPath 或 CSS 选择器提取数据,并将数据存储到定义的数据项中。

import scrapy
from myproject.items import MyItem

class MySpider(scrapy.Spider):
    name = 'myspider'
    allowed_domains = ['example.com']
    start_urls = ['https://example.com']

    def parse(self, response):
        # 解析响应内容
        item = MyItem()
        item['title'] = response.xpath('//title/text()').get()
        item['content'] = response.xpath('//p/text()').getall()
        item['url'] = response.url

        yield item

        # 继续请求其他页面
        next_page = response.xpath('//a[@class="next"]/@href').get()
        if next_page:
            yield response.follow(next_page, self.parse)

6. 数据存储

pipelines.py 文件中定义数据管道,处理抓取的数据并存储到文件、数据库等。

import json

class JsonWriterPipeline:
    def open_spider(self, spider):
        self.file = open('items.json', 'w')

    def close_spider(self, spider):
        self.file.close()

    def process_item(self, item, spider):
        line = json.dumps(dict(item)) + "\n"
        self.file.write(line)
        return item

settings.py 文件中启用数据管道:

ITEM_PIPELINES = {
    'myproject.pipelines.JsonWriterPipeline': 300,
}

7. 中间件

中间件用于处理请求和响应,例如设置用户代理、处理重试等。

class MyMiddleware:
    def process_request(self, request, spider):
        request.headers['User-Agent'] = 'MyApp/1.0'

    def process_response(self, request, response, spider):
        if response.status == 404:
            print(f"404 Not Found: {request.url}")
        return response

settings.py 文件中启用中间件:

DOWNLOADER_MIDDLEWARES = {
    'myproject.middlewares.MyMiddleware': 543,
}

8. 配置设置

settings.py 文件中配置项目的各种设置,例如请求延迟、并发请求等。

# 请求延迟
DOWNLOAD_DELAY = 1

# 并发请求
CONCURRENT_REQUESTS = 16

# 用户代理
USER_AGENT = 'MyApp/1.0'

# 禁用 cookies
COOKIES_ENABLED = False

# 重试设置
RETRY_ENABLED = True
RETRY_TIMES = 3

9. 部署和运行

9.1 本地运行

在本地开发环境中运行爬虫:

scrapy crawl myspider
9.2 部署到 Scrapy Cloud

Scrapy Cloud 是一个托管服务,可以方便地部署和管理 Scrapy 项目。

  1. 注册并登录 Scrapy Cloud。
  2. 创建一个新的项目。
  3. 将本地项目推送到 Scrapy Cloud。
scrapyc deploy

Selenium库:当需要与JavaScript动态加载的内容交互时使用,可以模拟浏览器行为。

1. 安装 Selenium 库

首先,你需要安装 Selenium 库。可以通过 pip 命令来安装:

pip install selenium

此外,还需要下载浏览器驱动程序(如 ChromeDriver),并将其路径添加到系统的环境变量中。你可以从 ChromeDriver 下载页面 下载适合你浏览器版本的驱动程序。

2. 基本用法

2.1 创建 WebDriver 对象

首先,需要从 selenium.webdriver 模块中导入相关类,并创建一个 WebDriver 对象。

from selenium import webdriver

# 创建 WebDriver 对象
driver = webdriver.Chrome()  # 使用 Chrome 浏览器
2.2 打开网页

使用 get 方法打开指定的网页。

driver.get('https://example.com')
2.3 关闭浏览器

完成操作后,使用 quit 方法关闭浏览器。

driver.quit()

3. 常见操作

3.1 查找元素

使用 find_element_by_* 方法查找单个元素,或使用 find_elements_by_* 方法查找多个元素。

# 查找单个元素
element = driver.find_element_by_id('element_id')
element = driver.find_element_by_name('element_name')
element = driver.find_element_by_class_name('element_class')
element = driver.find_element_by_tag_name('tag_name')
element = driver.find_element_by_link_text('link_text')
element = driver.find_element_by_partial_link_text('partial_link_text')
element = driver.find_element_by_xpath('//xpath_expression')
element = driver.find_element_by_css_selector('css_selector')

# 查找多个元素
elements = driver.find_elements_by_class_name('element_class')
3.2 操作元素

可以对找到的元素进行各种操作,如点击、输入文本等。

# 点击按钮
button = driver.find_element_by_id('submit_button')
button.click()

# 输入文本
input_field = driver.find_element_by_id('input_field')
input_field.send_keys('Hello, World!')

# 清空输入框
input_field.clear()
3.3 获取元素属性

可以获取元素的属性值。

# 获取元素的属性值
attribute_value = element.get_attribute('attribute_name')
print(attribute_value)
3.4 获取页面内容

可以获取页面的 HTML 内容。

# 获取页面的 HTML 内容
html_content = driver.page_source
print(html_content)

4. 处理动态内容

4.1 显式等待

使用 WebDriverWaitexpected_conditions 处理动态内容,等待某个条件满足后再进行操作。

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# 显式等待,直到某个元素可见
element = WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.ID, 'element_id'))
)

# 显式等待,直到某个元素可点击
element = WebDriverWait(driver, 10).until(
    EC.element_to_be_clickable((By.ID, 'submit_button'))
)
4.2 隐式等待

设置隐式等待时间,如果在指定时间内找不到元素,则抛出 NoSuchElementException 异常。

# 设置隐式等待时间为 10 秒
driver.implicitly_wait(10)

5. 高级用法

5.1 处理弹出窗口

可以处理浏览器的弹出窗口,如确认对话框、警告对话框等。

# 处理确认对话框
alert = driver.switch_to.alert
alert.accept()  # 点击“确定”
alert.dismiss()  # 点击“取消”

# 获取警告对话框的文本
alert_text = alert.text
print(alert_text)
5.2 处理多窗口

可以处理多个窗口或标签页。

# 获取当前窗口句柄
current_window = driver.current_window_handle

# 获取所有窗口句柄
all_windows = driver.window_handles

# 切换到新的窗口
driver.switch_to.window(all_windows[1])

# 切换回原来的窗口
driver.switch_to.window(current_window)
5.3 处理表单

可以处理表单的提交。

# 填写表单
username_field = driver.find_element_by_id('username')
password_field = driver.find_element_by_id('password')
submit_button = driver.find_element_by_id('submit_button')

username_field.send_keys('user123')
password_field.send_keys('pass456')
submit_button.click()

6. 示例:登录网站

下面是一个完整的示例,演示如何使用 Selenium 登录一个网站。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# 创建 WebDriver 对象
driver = webdriver.Chrome()

# 打开登录页面
driver.get('https://example.com/login')

# 等待用户名输入框出现
username_field = WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.ID, 'username'))
)

# 等待密码输入框出现
password_field = WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.ID, 'password'))
)

# 等待提交按钮出现
submit_button = WebDriverWait(driver, 10).until(
    EC.element_to_be_clickable((By.ID, 'submit_button'))
)

# 填写表单
username_field.send_keys('user123')
password_field.send_keys('pass456')

# 提交表单
submit_button.click()

# 等待登录成功后的页面元素出现
success_message = WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.ID, 'success_message'))
)

# 打印成功消息
print(success_message.text)

# 关闭浏览器
driver.quit()

数据存储

文件操作:学会将爬取的数据保存到本地文件中,如CSV、JSON等格式。

1. 保存为 CSV 文件

1.1 使用 csv 模块

Python 的标准库中有一个 csv 模块,可以方便地处理 CSV 文件。

import csv

# 示例数据
data = [
    ['Name', 'Age', 'City'],
    ['Alice', 25, 'New York'],
    ['Bob', 30, 'Los Angeles'],
    ['Charlie', 35, 'Chicago']
]

# 写入 CSV 文件
with open('output.csv', 'w', newline='') as csvfile:
    writer = csv.writer(csvfile)
    writer.writerows(data)

# 读取 CSV 文件
with open('output.csv', 'r') as csvfile:
    reader = csv.reader(csvfile)
    for row in reader:
        print(row)
1.2 使用 pandas 库

pandas 是一个强大的数据处理库,可以方便地处理和保存数据。

import pandas as pd

# 示例数据
data = {
    'Name': ['Alice', 'Bob', 'Charlie'],
    'Age': [25, 30, 35],
    'City': ['New York', 'Los Angeles', 'Chicago']
}

# 创建 DataFrame
df = pd.DataFrame(data)

# 保存为 CSV 文件
df.to_csv('output.csv', index=False)

# 读取 CSV 文件
df = pd.read_csv('output.csv')
print(df)

2. 保存为 JSON 文件

2.1 使用 json 模块

Python 的标准库中有一个 json 模块,可以方便地处理 JSON 数据。

import json

# 示例数据
data = [
    {'Name': 'Alice', 'Age': 25, 'City': 'New York'},
    {'Name': 'Bob', 'Age': 30, 'City': 'Los Angeles'},
    {'Name': 'Charlie', 'Age': 35, 'City': 'Chicago'}
]

# 写入 JSON 文件
with open('output.json', 'w') as jsonfile:
    json.dump(data, jsonfile, indent=4)

# 读取 JSON 文件
with open('output.json', 'r') as jsonfile:
    data = json.load(jsonfile)
    print(data)

3. 结合 Scrapy 保存数据

在 Scrapy 项目中,可以使用数据管道 (pipelines) 将数据保存到文件中。

3.1 保存为 CSV 文件

pipelines.py 文件中定义一个数据管道,将数据保存为 CSV 文件。

import csv

class CsvPipeline:
    def open_spider(self, spider):
        self.file = open('output.csv', 'w', newline='')
        self.writer = csv.writer(self.file)
        self.writer.writerow(['Name', 'Age', 'City'])

    def close_spider(self, spider):
        self.file.close()

    def process_item(self, item, spider):
        self.writer.writerow([item['name'], item['age'], item['city']])
        return item

settings.py 文件中启用数据管道:

ITEM_PIPELINES = {
    'myproject.pipelines.CsvPipeline': 300,
}
3.2 保存为 JSON 文件

pipelines.py 文件中定义一个数据管道,将数据保存为 JSON 文件。

import json

class JsonPipeline:
    def open_spider(self, spider):
        self.file = open('output.json', 'w')

    def close_spider(self, spider):
        self.file.close()

    def process_item(self, item, spider):
        line = json.dumps(dict(item)) + "\n"
        self.file.write(line)
        return item

settings.py 文件中启用数据管道:

ITEM_PIPELINES = {
    'myproject.pipelines.JsonPipeline': 300,
}

4. 结合 Selenium 保存数据

在使用 Selenium 抓取数据时,可以将数据保存到文件中。

from selenium import webdriver
import json

# 创建 WebDriver 对象
driver = webdriver.Chrome()

# 打开网页
driver.get('https://example.com')

# 提取数据
data = []
elements = driver.find_elements_by_css_selector('.item')
for element in elements:
    name = element.find_element_by_css_selector('.name').text
    age = int(element.find_element_by_css_selector('.age').text)
    city = element.find_element_by_css_selector('.city').text
    data.append({'Name': name, 'Age': age, 'City': city})

# 保存为 JSON 文件
with open('output.json', 'w') as jsonfile:
    json.dump(data, jsonfile, indent=4)

# 关闭浏览器
driver.quit()

数据库操作:了解如何使用SQLite、MySQL或MongoDB等数据库存储数据。

1. 使用 SQLite

SQLite 是一个轻量级的数据库引擎,非常适合小型项目和测试。

1.1 安装 sqlite3 模块

Python 标准库中已经包含了 sqlite3 模块,无需额外安装。

1.2 创建和连接数据库
import sqlite3

# 连接到 SQLite 数据库(如果不存在则创建)
conn = sqlite3.connect('example.db')

# 创建游标对象
cursor = conn.cursor()

# 创建表
cursor.execute('''
CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT,
    age INTEGER,
    city TEXT
)
''')

# 提交事务
conn.commit()
1.3 插入数据
# 插入数据
cursor.execute('INSERT INTO users (name, age, city) VALUES (?, ?, ?)', ('Alice', 25, 'New York'))
cursor.execute('INSERT INTO users (name, age, city) VALUES (?, ?, ?)', ('Bob', 30, 'Los Angeles'))

# 提交事务
conn.commit()
1.4 查询数据
# 查询数据
cursor.execute('SELECT * FROM users')
rows = cursor.fetchall()

for row in rows:
    print(row)
1.5 关闭连接
# 关闭连接
conn.close()

2. 使用 MySQL

MySQL 是一个广泛使用的开源关系型数据库管理系统。

2.1 安装 mysql-connector-python 库
pip install mysql-connector-python
2.2 创建和连接数据库
import mysql.connector

# 连接到 MySQL 数据库
conn = mysql.connector.connect(
    host='localhost',
    user='your_username',
    password='your_password',
    database='your_database'
)

# 创建游标对象
cursor = conn.cursor()

# 创建表
cursor.execute('''
CREATE TABLE IF NOT EXISTS users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100),
    age INT,
    city VARCHAR(100)
)
''')

# 提交事务
conn.commit()
2.3 插入数据
# 插入数据
cursor.execute('INSERT INTO users (name, age, city) VALUES (%s, %s, %s)', ('Alice', 25, 'New York'))
cursor.execute('INSERT INTO users (name, age, city) VALUES (%s, %s, %s)', ('Bob', 30, 'Los Angeles'))

# 提交事务
conn.commit()
2.4 查询数据
# 查询数据
cursor.execute('SELECT * FROM users')
rows = cursor.fetchall()

for row in rows:
    print(row)
2.5 关闭连接
# 关闭连接
conn.close()

3. 使用 MongoDB

MongoDB 是一个流行的 NoSQL 数据库,适用于处理大量非结构化数据。

3.1 安装 pymongo 库
pip install pymongo
3.2 创建和连接数据库
from pymongo import MongoClient

# 连接到 MongoDB
client = MongoClient('mongodb://localhost:27017/')

# 选择数据库
db = client['your_database']

# 选择集合
collection = db['users']

# 插入数据
data = [
    {'name': 'Alice', 'age': 25, 'city': 'New York'},
    {'name': 'Bob', 'age': 30, 'city': 'Los Angeles'}
]

# 插入多条数据
result = collection.insert_many(data)

# 打印插入的文档 ID
print(result.inserted_ids)
3.3 查询数据
# 查询数据
documents = collection.find()

for doc in documents:
    print(doc)
3.4 更新数据
# 更新数据
result = collection.update_one({'name': 'Alice'}, {'$set': {'age': 26}})
print(f"匹配到的文档数: {result.matched_count}, 修改的文档数: {result.modified_count}")
3.5 删除数据
# 删除数据
result = collection.delete_one({'name': 'Bob'})
print(f"删除的文档数: {result.deleted_count}")

4. 结合 Scrapy 存储数据

在 Scrapy 项目中,可以使用数据管道 (pipelines) 将数据存储到数据库中。

4.1 使用 SQLite

pipelines.py 文件中定义一个数据管道,将数据存储到 SQLite 数据库中。

import sqlite3

class SQLitePipeline:
    def open_spider(self, spider):
        self.conn = sqlite3.connect('example.db')
        self.cursor = self.conn.cursor()
        self.cursor.execute('''
        CREATE TABLE IF NOT EXISTS users (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            name TEXT,
            age INTEGER,
            city TEXT
        )
        ''')
        self.conn.commit()

    def close_spider(self, spider):
        self.conn.close()

    def process_item(self, item, spider):
        self.cursor.execute('INSERT INTO users (name, age, city) VALUES (?, ?, ?)', (item['name'], item['age'], item['city']))
        self.conn.commit()
        return item

settings.py 文件中启用数据管道:

ITEM_PIPELINES = {
    'myproject.pipelines.SQLitePipeline': 300,
}
4.2 使用 MySQL

pipelines.py 文件中定义一个数据管道,将数据存储到 MySQL 数据库中。

import mysql.connector

class MySQLPipeline:
    def open_spider(self, spider):
        self.conn = mysql.connector.connect(
            host='localhost',
            user='your_username',
            password='your_password',
            database='your_database'
        )
        self.cursor = self.conn.cursor()
        self.cursor.execute('''
        CREATE TABLE IF NOT EXISTS users (
            id INT AUTO_INCREMENT PRIMARY KEY,
            name VARCHAR(100),
            age INT,
            city VARCHAR(100)
        )
        ''')
        self.conn.commit()

    def close_spider(self, spider):
        self.conn.close()

    def process_item(self, item, spider):
        self.cursor.execute('INSERT INTO users (name, age, city) VALUES (%s, %s, %s)', (item['name'], item['age'], item['city']))
        self.conn.commit()
        return item

settings.py 文件中启用数据管道:

ITEM_PIPELINES = {
    'myproject.pipelines.MySQLPipeline': 300,
}
4.3 使用 MongoDB

pipelines.py 文件中定义一个数据管道,将数据存储到 MongoDB 数据库中。

from pymongo import MongoClient

class MongoDBPipeline:
    def open_spider(self, spider):
        self.client = MongoClient('mongodb://localhost:27017/')
        self.db = self.client['your_database']
        self.collection = self.db['users']

    def close_spider(self, spider):
        self.client.close()

    def process_item(self, item, spider):
        self.collection.insert_one(dict(item))
        return item

settings.py 文件中启用数据管道:

ITEM_PIPELINES = {
    'myproject.pipelines.MongoDBPipeline': 300,
}

进阶技术

数据清洗:使用Pandas等库对爬取的数据进行预处理,去除无效或错误的数据。

1. 安装 pandas 库

首先,确保你已经安装了 pandas 库。可以通过 pip 命令来安装:

pip install pandas

2. 基本用法

2.1 导入库
import pandas as pd
2.2 读取数据

可以从多种来源读取数据,例如 CSV 文件、Excel 文件、SQL 数据库等。

# 从 CSV 文件读取数据
df = pd.read_csv('data.csv')

# 从 Excel 文件读取数据
df = pd.read_excel('data.xlsx')

# 从 SQL 数据库读取数据
import sqlite3
conn = sqlite3.connect('database.db')
df = pd.read_sql_query('SELECT * FROM table_name', conn)

3. 常见的数据清洗任务

3.1 查看数据

查看数据的基本信息,包括前几行、列名、数据类型等。

# 查看前几行
print(df.head())

# 查看列名
print(df.columns)

# 查看数据类型
print(df.dtypes)

# 查看数据统计信息
print(df.describe())
3.2 处理缺失值

处理缺失值是数据清洗中常见的任务之一。

# 检查缺失值
print(df.isnull().sum())

# 删除含有缺失值的行
df.dropna(inplace=True)

# 填充缺失值
df.fillna(value=0, inplace=True)  # 用0填充
df.fillna(method='ffill', inplace=True)  # 前向填充
df.fillna(method='bfill', inplace=True)  # 后向填充
3.3 处理重复值

删除重复的行。

# 检查重复值
print(df.duplicated().sum())

# 删除重复行
df.drop_duplicates(inplace=True)
3.4 转换数据类型

将某些列的数据类型转换为其他类型。

# 转换数据类型
df['age'] = df['age'].astype(int)
df['salary'] = df['salary'].astype(float)
3.5 重命名列

重命名列名。

# 重命名列
df.rename(columns={'old_name': 'new_name'}, inplace=True)
3.6 处理异常值

检测和处理异常值。

# 检测异常值
q1 = df['age'].quantile(0.25)
q3 = df['age'].quantile(0.75)
iqr = q3 - q1
lower_bound = q1 - 1.5 * iqr
upper_bound = q3 + 1.5 * iqr

# 删除异常值
df = df[(df['age'] >= lower_bound) & (df['age'] <= upper_bound)]
3.7 字符串处理

处理字符串数据,例如去除空格、替换字符串等。

# 去除空格
df['name'] = df['name'].str.strip()

# 替换字符串
df['city'] = df['city'].str.replace('New York', 'NYC')
3.8 日期处理

处理日期数据,例如将字符串转换为日期格式。

# 转换日期格式
df['date'] = pd.to_datetime(df['date'], format='%Y-%m-%d')

4. 示例:综合数据清洗

下面是一个综合示例,展示如何使用 pandas 进行数据清洗。

import pandas as pd

# 从 CSV 文件读取数据
df = pd.read_csv('data.csv')

# 查看数据基本信息
print(df.head())
print(df.dtypes)

# 处理缺失值
print(df.isnull().sum())
df.dropna(subset=['name'], inplace=True)  # 删除 name 列有缺失值的行
df.fillna({'age': 0, 'salary': 0}, inplace=True)  # 用0填充 age 和 salary 列的缺失值

# 处理重复值
print(df.duplicated().sum())
df.drop_duplicates(inplace=True)

# 转换数据类型
df['age'] = df['age'].astype(int)
df['salary'] = df['salary'].astype(float)

# 重命名列
df.rename(columns={'old_name': 'new_name'}, inplace=True)

# 处理异常值
q1 = df['age'].quantile(0.25)
q3 = df['age'].quantile(0.75)
iqr = q3 - q1
lower_bound = q1 - 1.5 * iqr
upper_bound = q3 + 1.5 * iqr
df = df[(df['age'] >= lower_bound) & (df['age'] <= upper_bound)]

# 字符串处理
df['name'] = df['name'].str.strip()
df['city'] = df['city'].str.replace('New York', 'NYC')

# 日期处理
df['date'] = pd.to_datetime(df['date'], format='%Y-%m-%d')

# 查看清洗后的数据
print(df.head())

5. 保存清洗后的数据

将清洗后的数据保存到文件中,例如 CSV 文件或 Excel 文件。

# 保存到 CSV 文件
df.to_csv('cleaned_data.csv', index=False)

# 保存到 Excel 文件
df.to_excel('cleaned_data.xlsx', index=False)

异步编程:利用asyncio和aiohttp等库提高爬虫效率,实现并发请求。

1. 安装 aiohttp 库

首先,确保你已经安装了 aiohttp 库。可以通过 pip 命令来安装:

pip install aiohttp

2. 基本用法

2.1 导入库
import asyncio
import aiohttp
2.2 创建异步函数

使用 async def 定义异步函数。

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()
2.3 创建主函数

使用 asyncio.run 运行异步主函数。

async def main():
    urls = [
        'https://example.com',
        'https://example.org',
        'https://example.net'
    ]

    async with aiohttp.ClientSession() as session:
        tasks = [fetch(session, url) for url in urls]
        results = await asyncio.gather(*tasks)

    for result in results:
        print(result)

# 运行主函数
asyncio.run(main())

3. 处理请求结果

3.1 解析 HTML 内容

可以使用 BeautifulSouplxml 解析返回的 HTML 内容。

from bs4 import BeautifulSoup

async def fetch_and_parse(session, url):
    async with session.get(url) as response:
        html_content = await response.text()
        soup = BeautifulSoup(html_content, 'html.parser')
        title = soup.title.string
        return title

async def main():
    urls = [
        'https://example.com',
        'https://example.org',
        'https://example.net'
    ]

    async with aiohttp.ClientSession() as session:
        tasks = [fetch_and_parse(session, url) for url in urls]
        results = await asyncio.gather(*tasks)

    for result in results:
        print(result)

# 运行主函数
asyncio.run(main())

4. 限制并发请求数量

为了防止过多的并发请求导致服务器压力过大,可以使用 asyncio.Semaphore 限制并发请求数量。

import asyncio
import aiohttp
from bs4 import BeautifulSoup

semaphore = asyncio.Semaphore(10)  # 限制并发请求数量为10

async def fetch_and_parse(session, url):
    async with semaphore:
        async with session.get(url) as response:
            html_content = await response.text()
            soup = BeautifulSoup(html_content, 'html.parser')
            title = soup.title.string
            return title

async def main():
    urls = [
        'https://example.com',
        'https://example.org',
        'https://example.net'
    ]

    async with aiohttp.ClientSession() as session:
        tasks = [fetch_and_parse(session, url) for url in urls]
        results = await asyncio.gather(*tasks)

    for result in results:
        print(result)

# 运行主函数
asyncio.run(main())

5. 错误处理

在异步编程中,错误处理非常重要。可以使用 try-except 块来捕获和处理异常。

import asyncio
import aiohttp
from bs4 import BeautifulSoup

semaphore = asyncio.Semaphore(10)  # 限制并发请求数量为10

async def fetch_and_parse(session, url):
    try:
        async with semaphore:
            async with session.get(url) as response:
                html_content = await response.text()
                soup = BeautifulSoup(html_content, 'html.parser')
                title = soup.title.string
                return title
    except Exception as e:
        print(f"Error fetching {url}: {e}")
        return None

async def main():
    urls = [
        'https://example.com',
        'https://example.org',
        'https://example.net'
    ]

    async with aiohttp.ClientSession() as session:
        tasks = [fetch_and_parse(session, url) for url in urls]
        results = await asyncio.gather(*tasks)

    for result in results:
        if result is not None:
            print(result)

# 运行主函数
asyncio.run(main())

6. 结合 Scrapy 使用异步请求

虽然 Scrapy 本身是同步的,但可以通过 scrapy-asyncio 扩展来实现异步请求。

6.1 安装 scrapy-asyncio
pip install scrapy-asyncio
6.2 配置 Scrapy 项目

settings.py 文件中启用 scrapy-asyncio

ASYNCIO_EVENT_LOOP = 'uvloop'
6.3 创建异步爬虫

spiders 目录下创建一个新的异步爬虫文件,例如 async_spider.py

import scrapy
from scrapy.spiders import AsyncSpider
from scrapy.http import Request
from bs4 import BeautifulSoup

class AsyncSpiderExample(AsyncSpider):
    name = 'async_spider'
    allowed_domains = ['example.com']
    start_urls = ['https://example.com']

    async def parse(self, response):
        soup = BeautifulSoup(response.text, 'html.parser')
        title = soup.title.string
        print(f"Title: {title}")

        # 提取更多链接
        links = soup.find_all('a')
        for link in links:
            href = link.get('href')
            if href:
                yield Request(href, callback=self.parse)

代理和用户代理设置:为了避免被目标网站封禁IP,学习如何设置代理服务器和随机更换User-Agent。

1. 设置代理服务器

1.1 使用 requests 库

requests 库支持通过 proxies 参数设置代理服务器。

import requests

# 设置代理
proxies = {
    'http': 'http://123.45.67.89:8080',
    'https': 'https://123.45.67.89:8080'
}

# 发送请求
response = requests.get('https://example.com', proxies=proxies)

# 打印响应内容
print(response.text)
1.2 使用 aiohttp 库

aiohttp 库也支持通过 ProxyConnector 设置代理服务器。

import aiohttp
import asyncio

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    # 设置代理
    connector = aiohttp.TCPConnector(force_close=True)
    proxy = 'http://123.45.67.89:8080'
    
    async with aiohttp.ClientSession(connector=connector) as session:
        response = await fetch(session, 'https://example.com', proxy=proxy)
        print(response)

# 运行主函数
asyncio.run(main())

2. 随机更换 User-Agent

2.1 使用 requests 库

可以使用 headers 参数设置 User-Agent,并通过随机选择 User-Agent 来避免被封禁。

import requests
import random

# 定义 User-Agent 列表
user_agents = [
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36',
    'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'
]

# 随机选择一个 User-Agent
headers = {'User-Agent': random.choice(user_agents)}

# 发送请求
response = requests.get('https://example.com', headers=headers)

# 打印响应内容
print(response.text)
2.2 使用 aiohttp 库

aiohttp 中也可以通过 headers 参数设置 User-Agent。

import aiohttp
import asyncio
import random

# 定义 User-Agent 列表
user_agents = [
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36',
    'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'
]

async def fetch(session, url):
    # 随机选择一个 User-Agent
    headers = {'User-Agent': random.choice(user_agents)}
    
    async with session.get(url, headers=headers) as response:
        return await response.text()

async def main():
    async with aiohttp.ClientSession() as session:
        response = await fetch(session, 'https://example.com')
        print(response)

# 运行主函数
asyncio.run(main())

3. 结合 Scrapy 使用代理和随机更换 User-Agent

3.1 设置代理

在 Scrapy 中,可以通过中间件设置代理服务器。

3.1.1 创建中间件

middlewares.py 文件中创建一个中间件来设置代理。

import random

class ProxyMiddleware:
    def __init__(self):
        self.proxies = [
            'http://123.45.67.89:8080',
            'http://98.76.54.32:8080'
        ]

    def process_request(self, request, spider):
        proxy = random.choice(self.proxies)
        request.meta['proxy'] = proxy
3.1.2 启用中间件

settings.py 文件中启用中间件。

DOWNLOADER_MIDDLEWARES = {
    'myproject.middlewares.ProxyMiddleware': 750,
}
3.2 随机更换 User-Agent
3.2.1 创建中间件

middlewares.py 文件中创建一个中间件来随机更换 User-Agent。

import random

class RandomUserAgentMiddleware:
    def __init__(self):
        self.user_agents = [
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
            'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36',
            'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'
        ]

    def process_request(self, request, spider):
        user_agent = random.choice(self.user_agents)
        request.headers['User-Agent'] = user_agent
3.2.2 启用中间件

settings.py 文件中启用中间件。

DOWNLOADER_MIDDLEWARES = {
    'myproject.middlewares.RandomUserAgentMiddleware': 750,
}

验证码处理:对于包含验证码的登录过程,可能需要使用OCR技术或者第三方服务来识别验证码。

1. 使用 OCR 技术

1.1 安装必要的库

首先,确保你已经安装了 pytesseractPillow 库。pytesseract 是一个用于调用 Tesseract OCR 引擎的 Python 包,Pillow 是一个图像处理库。

pip install pytesseract pillow
1.2 下载并安装 Tesseract OCR

你需要下载并安装 Tesseract OCR 引擎。根据你的操作系统,下载和安装方法如下:

  • Windows: 从 Tesseract 官方 GitHub 页面 下载安装包。
  • macOS: 使用 Homebrew 安装:
    brew install tesseract
  • Linux: 使用包管理器安装:
    sudo apt-get install tesseract-ocr
1.3 使用 pytesseract 识别验证码
import pytesseract
from PIL import Image

# 读取验证码图片
image = Image.open('captcha.png')

# 使用 pytesseract 识别验证码
captcha_text = pytesseract.image_to_string(image)

# 打印识别结果
print(captcha_text)

2. 使用第三方服务

2.1 使用 2Captcha

2Captcha 是一个常用的第三方验证码识别服务。它提供了一个 API,可以轻松地将验证码发送给他们的服务器进行识别。

2.1.1 注册并获取 API 密钥

首先,注册一个 2Captcha 账户并获取 API 密钥。

2.1.2 安装 2captcha-python 库
pip install 2captcha-python
2.1.3 使用 2Captcha 识别验证码
from twocaptcha import TwoCaptcha
import requests
from PIL import Image

# 初始化 2Captcha 客户端
solver = TwoCaptcha('YOUR_API_KEY')

# 读取验证码图片
with open('captcha.png', 'rb') as f:
    captcha_image = f.read()

# 发送验证码图片到 2Captcha 服务器
result = solver.normal(captcha_image)

# 打印识别结果
print(result['code'])

3. 综合示例:使用 OCR 和第三方服务处理验证码登录

下面是一个综合示例,展示如何使用 OCR 技术和第三方服务处理包含验证码的登录过程。

3.1 使用 OCR 技术
import requests
from bs4 import BeautifulSoup
import pytesseract
from PIL import Image

# 获取登录页面
login_url = 'https://example.com/login'
response = requests.get(login_url)
soup = BeautifulSoup(response.text, 'html.parser')

# 获取验证码图片 URL
captcha_img_url = soup.find('img', {'id': 'captcha'}).get('src')

# 下载验证码图片
captcha_response = requests.get(captcha_img_url)
with open('captcha.png', 'wb') as f:
    f.write(captcha_response.content)

# 使用 pytesseract 识别验证码
captcha_text = pytesseract.image_to_string(Image.open('captcha.png')).strip()

# 构建登录请求
login_data = {
    'username': 'your_username',
    'password': 'your_password',
    'captcha': captcha_text
}

# 发送登录请求
response = requests.post(login_url, data=login_data)

# 打印登录结果
print(response.text)
3.2 使用 2Captcha
import requests
from bs4 import BeautifulSoup
from twocaptcha import TwoCaptcha

# 初始化 2Captcha 客户端
solver = TwoCaptcha('YOUR_API_KEY')

# 获取登录页面
login_url = 'https://example.com/login'
response = requests.get(login_url)
soup = BeautifulSoup(response.text, 'html.parser')

# 获取验证码图片 URL
captcha_img_url = soup.find('img', {'id': 'captcha'}).get('src')

# 下载验证码图片
captcha_response = requests.get(captcha_img_url)
with open('captcha.png', 'wb') as f:
    f.write(captcha_response.content)

# 发送验证码图片到 2Captcha 服务器
result = solver.normal('captcha.png')

# 获取识别结果
captcha_text = result['code']

# 构建登录请求
login_data = {
    'username': 'your_username',
    'password': 'your_password',
    'captcha': captcha_text
}

# 发送登录请求
response = requests.post(login_url, data=login_data)

# 打印登录结果
print(response.text)

4. 处理复杂验证码

对于复杂的验证码(如扭曲的字符、干扰线等),简单的 OCR 技术可能无法准确识别。在这种情况下,可以考虑以下几种方法:

  • 训练自定义模型:使用深度学习框架(如 TensorFlow 或 PyTorch)训练自定义的验证码识别模型。
  • 使用更专业的第三方服务:除了 2Captcha,还有其他专业服务如 Anti-Captcha、Capmonster 等。
  • 手动验证:在某些情况下,可以设计一个流程,将验证码发送给人类进行手动验证。

反爬虫策略:了解常见的反爬虫机制,并学习如何绕过这些限制。

1. 常见的反爬虫机制

1.1 IP 封禁

网站可能会记录访问者的 IP 地址,并在短时间内检测到大量请求时封禁该 IP。

1.2 User-Agent 检测

网站会检查请求头中的 User-Agent,如果发现不是常见的浏览器 User-Agent,可能会拒绝请求。

1.3 验证码

网站会在登录或关键操作时显示验证码,以防止自动化访问。

1.4 JavaScript 渲染

一些网站使用 JavaScript 动态加载内容,普通的 HTTP 请求无法获取这些内容。

1.5 Cookies 和 Session

网站可能会通过设置 Cookies 和 Session 来跟踪用户的会话状态,防止未授权访问。

1.6 频率限制

网站可能会限制每个 IP 在一定时间内的请求次数,超过限制后会暂时封禁该 IP。

2. 绕过反爬虫限制的策略

2.1 使用代理服务器

通过使用代理服务器,可以隐藏真实的 IP 地址,避免被封禁。

2.1.1 使用 requests 库
import requests
import random

# 定义代理列表
proxies = [
    'http://123.45.67.89:8080',
    'http://98.76.54.32:8080'
]

# 随机选择一个代理
proxy = random.choice(proxies)

# 发送请求
response = requests.get('https://example.com', proxies={'http': proxy, 'https': proxy})

# 打印响应内容
print(response.text)
2.1.2 使用 aiohttp 库
import aiohttp
import asyncio
import random

# 定义代理列表
proxies = [
    'http://123.45.67.89:8080',
    'http://98.76.54.32:8080'
]

async def fetch(session, url):
    # 随机选择一个代理
    proxy = random.choice(proxies)
    
    async with session.get(url, proxy=proxy) as response:
        return await response.text()

async def main():
    async with aiohttp.ClientSession() as session:
        response = await fetch(session, 'https://example.com')
        print(response)

# 运行主函数
asyncio.run(main())
2.2 随机更换 User-Agent

通过随机更换 User-Agent,可以模拟不同的浏览器访问,降低被检测的风险。

2.2.1 使用 requests 库
import requests
import random

# 定义 User-Agent 列表
user_agents = [
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36',
    'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'
]

# 随机选择一个 User-Agent
headers = {'User-Agent': random.choice(user_agents)}

# 发送请求
response = requests.get('https://example.com', headers=headers)

# 打印响应内容
print(response.text)
2.2.2 使用 aiohttp 库
import aiohttp
import asyncio
import random

# 定义 User-Agent 列表
user_agents = [
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36',
    'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'
]

async def fetch(session, url):
    # 随机选择一个 User-Agent
    headers = {'User-Agent': random.choice(user_agents)}
    
    async with session.get(url, headers=headers) as response:
        return await response.text()

async def main():
    async with aiohttp.ClientSession() as session:
        response = await fetch(session, 'https://example.com')
        print(response)

# 运行主函数
asyncio.run(main())
2.3 处理验证码

使用 OCR 技术或第三方服务来识别验证码。

2.3.1 使用 OCR 技术
import pytesseract
from PIL import Image

# 读取验证码图片
image = Image.open('captcha.png')

# 使用 pytesseract 识别验证码
captcha_text = pytesseract.image_to_string(image).strip()

# 打印识别结果
print(captcha_text)
2.3.2 使用 2Captcha
from twocaptcha import TwoCaptcha
import requests

# 初始化 2Captcha 客户端
solver = TwoCaptcha('YOUR_API_KEY')

# 下载验证码图片
captcha_response = requests.get('https://example.com/captcha.png')
with open('captcha.png', 'wb') as f:
    f.write(captcha_response.content)

# 发送验证码图片到 2Captcha 服务器
result = solver.normal('captcha.png')

# 获取识别结果
captcha_text = result['code']

# 打印识别结果
print(captcha_text)
2.4 处理 JavaScript 渲染

使用 SeleniumPyppeteer 等库来处理 JavaScript 渲染的页面。

2.4.1 使用 Selenium
from selenium import webdriver

# 创建 WebDriver 对象
driver = webdriver.Chrome()

# 打开网页
driver.get('https://example.com')

# 获取动态加载的内容
content = driver.page_source

# 打印内容
print(content)

# 关闭浏览器
driver.quit()
2.4.2 使用 Pyppeteer
import asyncio
from pyppeteer import launch

async def main():
    # 启动浏览器
    browser = await launch()
    page = await browser.newPage()

    # 打开网页
    await page.goto('https://example.com')

    # 获取动态加载的内容
    content = await page.content()

    # 打印内容
    print(content)

    # 关闭浏览器
    await browser.close()

# 运行主函数
asyncio.run(main())
2.5 处理 Cookies 和 Session

保持会话状态,确保每次请求都携带相同的 Cookies。

2.5.1 使用 requests 库
import requests

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

# 发送请求
response = session.get('https://example.com')

# 打印响应内容
print(response.text)
2.5.2 使用 aiohttp 库
import aiohttp
import asyncio

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    # 创建会话对象
    async with aiohttp.ClientSession() as session:
        response = await fetch(session, 'https://example.com')
        print(response)

# 运行主函数
asyncio.run(main())
2.6 控制请求频率

通过控制请求频率,避免因请求过于频繁而被封禁。

2.6.1 使用 time.sleep
import requests
import time

urls = ['https://example.com/page1', 'https://example.com/page2']

for url in urls:
    response = requests.get(url)
    print(response.text)
    time.sleep(1)  # 每次请求之间暂停1秒
2.6.2 使用 asyncio.sleep
import aiohttp
import asyncio

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    urls = ['https://example.com/page1', 'https://example.com/page2']
    
    async with aiohttp.ClientSession() as session:
        for url in urls:
            response = await fetch(session, url)
            print(response)
            await asyncio.sleep(1)  # 每次请求之间暂停1秒

# 运行主函数
asyncio.run(main())

法律和伦理(所有该博文的实例代码不得复制过去做违法的事)

遵守法律法规:在编写爬虫时,确保遵守相关的法律和网站的服务条款。

尊重网站资源:合理控制爬虫的访问频率,避免给目标网站带来过大的负担。

实践项目(请听下回讲解)

实战练习:通过实际项目来应用所学知识,例如抓取新闻标题、股票价格、社交媒体数据等。

标签:Python,text,爬虫,element,详解,print,import,requests,response
From: https://blog.csdn.net/speaking_me/article/details/143216181

相关文章

  • Keil C51 9.61__官网“最新版“下载、安装及相关提示( 保姆级教程, 安装过程详解, 附
     前言Keil5常用的分两个版本,C51 和MDK。C51用于编译8051内核的单片机程序,譬如AT89C51、STC89C51、STC98C52等。MDK用于编译STM32、GD32等ARM32位内核单片机程序。‌KeilC51‌是由KeilSoftwareCompany开发的,专门用于8051微控制器的软件开发系统。它支持8051系列的所有......
  • 【动态绘图】python 动态柱形图 动态折线图 bar_chart_race sjvisualizer
    本文主要介绍如何使用Python的bar_chart_race和sjvisualizer模块绘制动态柱形图和动态折线图。关于sjvisualizer包使用详细可见【动态绘图】上。一、实验环境1.1操作系统及Python环境本实验的所使用的操作系统为Windows1064位,Python版本为Python3.12.4,Python编译器......
  • 【Azure Function】Python Function部署到Azure后报错No module named '_cffi_backend
    问题描述本地使用Python编写的FunctionApp,发布到AzureFunction后,出现 _cffi_backendmodule无法找到的报错。ERROR:Error:Nomodulenamed'_cffi_backend',Cannotfindmodule.Pleasechecktherequirements.txtfileforthemissingmodule.Formoreinfo,plea......
  • 【Python入门】7天速成Python网络爬虫高手,urllib从零基础到实战只需一篇
    ......
  • Java类和对象详解(上)
    目录前言 一.类和对象的定义1.什么是一个类?2.类的定义格式 3.一个类中应该有什么 4.什么是对象二.类的实例化1.什么是实例化?2.实例化在内存中的使用情况: 三.构造方法(构造器)1.什么是构造方法2. 默认初始化3.this关键字3.1为什么要有this关键字3.2什么是thi......
  • 日语学习《红宝书新日本语能力考试N1·N2·N3·N4·N5文字词汇(详解+练习)》PDF分享
    ​​《红宝书:新日本语能力考试文字词汇(详解+练习)》系列丛书自出版以来,广受好评,成为很多参加能力考试的学习者的必备用书。《红宝书:新日本语能力考试文字词汇(详解+练习)》按新日语能力考试指南和新真题编写,收录词汇量达6300多个:涵盖必须掌握的重点词汇3324个,涵盖重要补充词汇300......
  • Java类和对象详解(下)
    目录前言:一.static关键字 1.static修饰成员变量2..static修饰成员方法3.静态代码块 二.代码块 1.普通代码块2.静态代码块3.静态代码块三.继承1.什么是继承2.为什么要继承3.继承的使用 4.父类的访问(super关键字)5. 子类构造方法6.代码执行顺序 7.组......
  • python: Parent-child form operations
     #encoding:utf-8#版權所有2024©塗聚文有限公司#許可資訊查看:言語成了邀功的功臣,還需要行爲每日來值班嗎?#描述:主、子表單窗體傳值Parent-childformoperations#Author:geovindu,GeovinDu塗聚文.#IDE:PyCharm2023.1python3.11#OS......
  • java启动命令详解
    java-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8002-server-Xms4g-Xmx6g-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/data/data/dump.bin-Dfile.encoding=UTF-8-Djava.awt.headless=true-XX:+UseG1GC-XX:MaxGCPauseMillis=200-XX:G1H......
  • python实战(二)——房屋价格回归建模
    一、任务背景    本章将使用一个经典的Kaggle数据集——HousePrices-AdvancedRegressionTechniques进行回归建模的讲解。这是一个房价数据集,与我们熟知的波士顿房价数据集类似,但是特征数量要更多,数据也要更为复杂一些。下面,我们将使用这个房价数据进行机器学习中......