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

基础知识

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 = 20if 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到4print(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 mathprint(math.sqrt(16))  # 输出: 4.0# 导入特定函数
from math import sqrtprint(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 requestsresponse = requests.get('https://api.example.com/data')
status_code = response.status_code
print(f"状态码: {status_code}")
获取响应头
import requestsresponse = requests.get('https://api.example.com/data')
headers = response.headers
print(f"响应头: {headers}")
获取响应体
import requestsresponse = 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 requestsheaders = {'User-Agent': 'MyApp/1.0','Content-Type': 'application/json'
}response = requests.get('https://api.example.com/data', headers=headers)
print(response.text)
设置超时

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

import requestsresponse = 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__.pyspider1.py    # 爬虫文件

3. 编写爬虫

3.1 创建爬虫

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

import scrapyclass MySpider(scrapy.Spider):name = 'myspider'  # 爬虫名称allowed_domains = ['example.com']  # 允许的域名start_urls = ['https://example.com']  # 起始URLdef 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 scrapyclass MyItem(scrapy.Item):title = scrapy.Field()content = scrapy.Field()url = scrapy.Field()

5. 数据提取

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

import scrapy
from myproject.items import MyItemclass 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.urlyield item# 继续请求其他页面next_page = response.xpath('//a[@class="next"]/@href').get()if next_page:yield response.follow(next_page, self.parse)

6. 数据存储

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

import jsonclass 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 csvclass 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 jsonclass 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').textage = int(element.find_element_by_css_selector('.age').text)city = element.find_element_by_css_selector('.city').textdata.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 sqlite3class 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.connectorclass 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 MongoClientclass 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 BeautifulSoupasync 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.stringreturn titleasync 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 BeautifulSoupsemaphore = asyncio.Semaphore(10)  # 限制并发请求数量为10async 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.stringreturn titleasync 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 BeautifulSoupsemaphore = asyncio.Semaphore(10)  # 限制并发请求数量为10async 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.stringreturn titleexcept Exception as e:print(f"Error fetching {url}: {e}")return Noneasync 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 BeautifulSoupclass 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.stringprint(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 asyncioasync 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-Agentheaders = {'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 randomclass 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 randomclass 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-Agentheaders = {'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 launchasync 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 asyncioasync 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 timeurls = ['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 asyncioasync 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())

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

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

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/883053.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【YOLOv11】制作使用YOLOv11的docker环境

目录 一 安装docker 1 安装依赖 2 添加docker官网 GPG 密钥、设置stable 仓库 3 安装 4 使用 二 环境制作 ① 拉基础镜像 ② 起容器 ③ 安装Anaconda3 ④ 安装YOLO11 ⑤ /root/.bashrc ⑥ 退出容器 ⑦ 保存镜像 ⑧ 镜像的使用 一 安装docker ubuntu:20.04 1 安装…

Java项目-基于springboot框架的人职匹配推荐系统项目实战(附源码+文档)

作者&#xff1a;计算机学长阿伟 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、ElementUI等&#xff0c;“文末源码”。 开发运行环境 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBoot、Vue、Mybaits Plus、ELementUI工具&#xff1a;IDEA/…

【LeetCode】每日一题 2024_10_24 找到连续赢 K 场比赛的第一位玩家(模拟/脑筋急转弯)

前言 每天和你一起刷 LeetCode 每日一题~ 1024 程序员节快乐~ LeetCode 启动&#xff01; 题目&#xff1a;找到连续赢 K 场比赛的第一位玩家 代码与解题思路 题目让我们从第一个元素开始让数组中的元素排队一个个打擂台&#xff0c;直到找到最先赢下 k 次的元素编号 因为…

代码随想录算法训练营第六天|454四数相加II、 383赎金信、15三数之和、18四数之和

day06 1. 454四数相加II 首先定义 一个unordered_map&#xff0c;key放a和b两数之和&#xff0c;value 放a和b两数之和出现的次数。遍历大A和大B数组&#xff0c;统计两个数组元素之和&#xff0c;和出现的次数&#xff0c;放到map中。定义int变量count&#xff0c;用来统计 …

系统性能优化的终极武器,一键让你的电脑焕发第二春

作为Windows系统维护的得力助手&#xff0c;PC Fresh为用户带来全方位的电脑优化解决方案。这款智能系统工具采用先进的检测引擎&#xff0c;不仅能够实时监控计算机的运行状态&#xff0c;更可以精准定位影响性能的潜在问题。通过智能诊断技术&#xff0c;软件会针对每台电脑的…

多去尝试 AI 产品经理面试,你会意外发现……

前言 这两天跟很多做程序员的朋友聊天&#xff0c;怎么看全网火爆的大模型。让我挺意外的是&#xff0c;大家的反馈普遍都很焦虑 。 在AI大模型微调领域的产品经理面试中&#xff0c;总会遇到一系列与技术细节、项目经验、市场趋势以及职业规划相关的问题。以下是一些建议的面…

GEE引擎传奇UI界面修改教程

还记得小林之前给大家分享了gom引擎UI界面编辑教程&#xff0c;今天给大家分享一下gee引擎UI界面修改教程 首先打开登录器生成器-客户端界面设置 在客户端界面设置这里可以自定义UI素材&#xff0c;也可以直接在原素材上编辑主界面 传奇根目录指向的是你的传奇客户端根目录&am…

【LaTeX】调整itemize中item的间距

LaTeX中调整itemize中item的间距 1. 使用 \setlength 调整间距2. 使用 enumitem 宏包来更灵活地调整 在 LaTeX 中&#xff0c;调整 itemize 列表中各项 (item) 的间距可以通过以下方法实现&#xff1a; 1. 使用 \setlength 调整间距 通过 \setlength 调整列表项之间的间距。两…

【随手笔记】远程升级之如何平衡下载包大小与速率?

1. 远程升级基本信息 使用NB_BC26模组&#xff0c;通过AT指令使用TCP的协议与公司后台交互升级的固件为BIN文件&#xff0c;使用原始固件包升级&#xff0c;未使用差分方式原始固件包有110K,大小左右&#xff0c;固件的存储为外置的FLASH W25Q16,w25q16最小存储单位为页&#…

BurpSuit 安装Jpython 和Json-Hunter脚本

0x00下载Jpython jpython2.7.2下载的人最多&#xff0c;所以我就安装2.7.2了 Central Repository: org/python/jython-standalone/2.7.2 点击下载即可。 0x01BP设置jpython环境 重点&#xff1a;Jpython和Jsonp-Hunter一定要放在英文目录下。 0x02安装Jsonp-Hunter https:…

基于Python和OpenCV的疲劳检测系统设计与实现

项目运行 需要先安装Python的相关依赖&#xff1a;pymysql&#xff0c;Django3.2.8&#xff0c;pillow 使用pip install 安装 第一步&#xff1a;创建数据库 第二步&#xff1a;执行SQL语句&#xff0c;.sql文件&#xff0c;运行该文件中的SQL语句 第三步&#xff1a;修改源…

《Windows PE》6.4.2 远程注入DLL

实验四十七&#xff1a;远程注入DLL 写一个窗口程序&#xff0c;将一个dll通过远程注入的方法&#xff0c;注入到第三章的示例程序PEHeader.exe中&#xff0c;支持32位和64位PE。 ●dll.c /*------------------------------------------------------------------------FileNam…

《PP-OCRv1》论文精读:PaddleOCR是目前SOTA级别的OCR开源技术(截止2024年10月)

PP-OCR: A Practical Ultra Lightweight OCR System论文地址PP-OCRv2: Bag of Tricks for Ultra Lightweight OCR System论文地址PP-OCRv3: More Attempts for the Improvement of Ultra Lightweight OCR System论文地址PaddleOCR Github OCR工具库 43.5K个star PP-OCRv1由百度…

矩阵基础知识

矩阵定义 矩阵的定义 1.矩阵是由一组数按照矩形排列而成的数表。矩阵通常用大写字母表示&#xff0c;例如 AA、BB 等。矩阵中的每个数称为矩阵的元素或元。 一个 mn的矩阵 AA 可以表示为&#xff1a; 其中 aij表示矩阵 A中第i行第j列的元素。 矩阵的维度 1.矩阵的维度由它…

经典功率谱估计的原理及MATLAB仿真(自相关函数BT法、周期图法、bartlett法、welch法)

经典功率谱估计的原理及MATLAB仿真&#xff08;自相关函数BT法、周期图法、bartlett法、welch法&#xff09; 文章目录 前言一、BT法二、周期图法三、Bartlett法四、welch法五、MATLAB仿真六、MATLAB详细代码总结 前言 经典功率谱估计方法包括BT法&#xff08;对自相关函数求傅…

python实现onvif协议下控制摄像头变焦,以及融合人形识别与跟踪控制

#1024程序员节 | 征文# 这两天才因为项目需要&#xff0c;对网络摄像头的视频采集以及实现人形识别与跟踪技术。对于onvif协议自然起先也没有任何的了解。但是购买的摄像头是SONY网络头是用在其他地方的。因为前期支持探究项目解决方案&#xff0c;就直接拿来做demo测试使用。 …

react18中在列表项中如何使用useRef来获取每项的dom对象

在react中获取dom节点都知道用ref&#xff0c;但是在一个列表循环中&#xff0c;这样做是行不通的&#xff0c;需要做进一步的数据处理。 实现效果 需求&#xff1a;点击每张图片&#xff0c;当前图片出现在可视区域。 代码实现 .box{border: 1px solid #000;list-style: …

微前端架构新选择:micro-app 框架一文全解析

目录 前言技术方案沙箱withiframe 环境变量主应用生命周期子应用生命周期初始化更新卸载缓存 JS 沙箱样式隔离元素隔离路由系统⭐数据通信⭐资源系统预加载umd 模式其他功能调试工具 前言 https://micro-zoe.github.io/micro-app/ micro-app 是由京东前端团队推出的一款微前端…

基于springboot美食商城推荐系统

基于springboot美食商城推荐系统 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;idea 源码获取&#xff1a;https://downlo…

iOS调试真机出现的 “__llvm_profile_initialize“ 错误

一、错误形式&#xff1a; app启动就崩溃&#xff0c;如下&#xff1a; Demo__llvm_profile_initialize:0x1045f7ab0 <0>: stp x20, x19, [sp, #-0x20]!0x1045f7ab4 <4>: stp x29, x30, [sp, #0x10]0x1045f7ab8 <8>: add x29, sp, #0x100x1…