当前位置: 首页 > ds >正文

Python 爬虫入门

文章目录

  • 1. 网络爬虫简介
    • 1.1. 什么是网络爬虫
    • 1.2. 网络爬虫工作原理
    • 1.3. 常见的 Python 爬虫库介绍
    • 1.4. 网络爬虫需要注意的重要事项
      • 1.4.1. 网络爬虫需要注意的重要事项
      • 1.4.2. 爬虫与反爬的攻防关系
  • 2. 如何查看和遵守 robots.txt
    • 2.1. 如何查看 robots.txt 文件
      • 2.1.1. 直接访问: 将网址后面加上"/robots.txt"
      • 2.1.2. 通过 requests 代码查看
    • 2.2. robots.txt 文件典型内容示例
    • 2.3. robots.txt 文件分析图解
  • 3. Python 爬虫操作
    • 3.1. 爬虫请求
      • 3.1.1. 请求方式
      • 3.1.2. 请求 URL
      • 3.1.3. 请求头
      • 3.1.4. 请求体
    • 3.2. 爬虫响应
      • 3.2.1. 响应状态码
      • 3.2.2. respone header
      • 3.2.3. preview 就是网页源代码
  • 4. 基础爬虫开发
    • 4.1. 爬虫实例1
    • 4.2. 爬虫实例2
      • 4.2.1. 单线程版
      • 4.2.2. 多线程版

1. 网络爬虫简介

参考:https://juejin.cn/post/7494635102174036003

1.1. 什么是网络爬虫

网络爬虫(Web Crawler)是一种自动获取网页内容的程序。它可以访问网站,抓取页面内容,并从中提取有价值的数据。在信息爆炸的时代,爬虫技术可以帮助我们高效地收集、整理和分析互联网上的海量数据。

1.2. 网络爬虫工作原理

网络爬虫虽然种类多样,但基本工作原理是相似的。下图展示了爬虫的典型工作流程:
在这里插入图片描述
网络爬虫的工作流程通常遵循一个循环往复的过程,主要包括以下几个环节:
初始化种子URL: 爬虫从一组预定义的起始 URL(称为种子URL)开始工作。这些 URL 是爬取过程的入口点,类似于探索迷宫的起点。
URL 队列管理: 爬虫维护一个待爬取的 URL 队列。初始时,队列中只有种子 URL,随着爬取过程的推进,新发现的 URL 会不断加入队列。
URL 调度器: 负责从 URL 队列中选择下一个要爬取的 URL。调度器会考虑各种因素,如 URL 优先级、访问频率限制、网站礼仪(robots.txt)等。
网页下载: 爬虫向目标 URL 发送 HTTP 请求,获取网页内容。这一步可能会处理各种 HTTP 状态码、重定向、超时等情况。
内容解析: 获取到网页内容后,爬虫会解析 HTML/XML 结构,提取有价值的数据。常用的解析方法包括正则表达式、XPath、CSS选择器或专门的解析库(如BeautifulSoup)。
数据过滤与存储: 对提取的数据进行清洗、去重、格式化等处理,然后存储到文件、数据库或其他存储系统中。
URL提取: 从已下载的页面中提取新的URL链接,这些新URL经过筛选后(去除重复、不符合规则的URL)加入到URL队列中,等待后续爬取。
循环迭代: 重复上述过程,直到达到预定的终止条件,如队列为空、达到最大爬取数量或时间限制等。
在实际应用中,爬虫系统还会增加很多功能模块,如反爬处理、分布式协作、失败重试、数据验证等,以提高爬取的效率、稳定性和准确性。

1.3. 常见的 Python 爬虫库介绍

为了应对不同的爬取需求和反爬挑战,Python生态系统提供了多种爬虫相关的库。以下是一些最常用的工具:

库名特点适用场景
Requests简单易用的HTTP库基础网页获取
BeautifulSoupHTML/XML解析器静态网页内容提取
Scrapy全功能爬虫框架大型爬虫项目
Selenium浏览器自动化工具需要JavaScript渲染的网页
PyppeteerPuppeteer的Python版本复杂的动态网页
lxml高效的XML/HTML解析器需要高性能解析的场景
PyQuery类 jQuery 语法的解析库熟悉 jQuery 的开发者
aiohttp异步HTTP客户端/服务器高并发爬虫

掌握了这些工具后,我们就能应对各种网页爬取的需求。爬虫技术的应用场景也非常广泛。

1.4. 网络爬虫需要注意的重要事项

1.4.1. 网络爬虫需要注意的重要事项

法律与道德考量
尊重robots.txt:这是网站指定爬虫行为的标准文件,应当遵守。
识别网站的爬虫政策:有些网站明确禁止爬虫,有些则有特定的API可用。
避免过度请求:高频率的请求可能导致服务器负担过重。
遵守数据使用条款:确保你对抓取的数据的使用符合网站的条款。
注意个人隐私数据:不应爬取和存储涉及个人隐私的数据。
技术注意事项
设置合理的请求间隔:使用time.sleep()控制请求频率。
使用代理IP:避免IP被封禁。
模拟真实用户行为:添加请求头,随机调整请求间隔。
处理反爬机制:验证码识别、JavaScript渲染等。
异常处理:网络连接、解析错误等都需要妥善处理。
性能考虑
异步爬取:使用asyncio和aiohttp提高效率。
分布式爬取:对于大规模爬取任务,考虑使用多机协作。
数据存储优化:选择合适的存储方式(文件、数据库等)。

1.4.2. 爬虫与反爬的攻防关系

随着互联网数据价值的不断提升,爬虫技术与反爬技术之间形成了一种此消彼长的攻防关系。这种关系呈现出明显的阶段性特征,从最初的简单对抗发展到如今的复杂博弈。
在早期阶段,爬虫通常以简单的HTTP请求方式获取网页内容,网站则主要通过访问频率限制来防御。爬虫工程师很快发现,只需在请求中添加随机延时就能有效规避这类限制。这种基础层面的对抗促使网站开发者升级防御策略。
随着对抗升级,网站开始实施更复杂的防御措施,例如检测请求头中的用户代理信息,以及限制单一IP的访问次数。爬虫技术随之调整,不仅能够伪装请求头信息,还发展出代理IP池技术,通过不断切换IP地址来绕过访问限制。这一阶段的特点是技术门槛明显提高,双方对抗更加精细化。
当前,我们已进入高级对抗阶段。网站普遍采用验证码挑战、前端JavaScript渲染数据以及用户行为分析等技术手段。爬虫则相应发展出验证码识别、浏览器自动化以及用户行为模拟等对抗技术。例如,Selenium和Puppeteer等工具能够模拟真实浏览器环境,执行JavaScript并渲染页面,而机器学习算法则用于识别各类验证码。
这种持续升级的攻防关系,某种程度上推动了双方技术的不断创新与进步。对于数据分析工作而言,理解这种技术演进对于构建稳定的数据获取渠道至关重要。

2. 如何查看和遵守 robots.txt

作为负责任的爬虫开发者,我们应该尊重网站所有者的意愿。robots.txt 是网站根目录下的一个文本文件,用于告诉爬虫哪些页面可以爬取,哪些不可以。遵守 robots.txt 是网络爬虫的基本道德准则。

2.1. 如何查看 robots.txt 文件

2.1.1. 直接访问: 将网址后面加上"/robots.txt"

https://www.baidu.com/robots.txt

在这里插入图片描述

2.1.2. 通过 requests 代码查看

import requestsdef get_robots_txt(url):# 确保URL格式正确if not url.startswith('http'):url = 'https://' + url# 移除URL末尾的斜杠(如果有)if url.endswith('/'):url = url[:-1]# 获取robots.txt文件robots_url = url + '/robots.txt'try:response = requests.get(robots_url)if response.status_code == 200:print(f"成功获取 {robots_url}")return response.textelse:print(f"无法获取robots.txt,状态码: {response.status_code}")return Noneexcept Exception as e:print(f"发生错误: {e}")return None# 使用示例
robots_content = get_robots_txt('www.baidu.com')
print(robots_content)

在这里插入图片描述

2.2. robots.txt 文件典型内容示例

User-agent: *
Disallow: /private/
Disallow: /admin/
Allow: /public/
Crawl-delay: 10

解释:
User-agent: * - 适用于所有爬虫
Disallow: /private/ - 禁止爬取/private/目录下的内容
Allow: /public/ - 允许爬取/public/目录下的内容
Crawl-delay: 10 - 建议爬虫每次请求之间间隔10秒

2.3. robots.txt 文件分析图解

在这里插入图片描述
理解了网站的爬取规则后,我们可以开始实际的爬虫编写。下面是一个简单的 Python 爬虫示例,展示了基本的爬取过程。

3. Python 爬虫操作

3.1. 爬虫请求

3.1.1. 请求方式

常见的请求方式:GET / POST

3.1.2. 请求 URL

url 全球统一资源定位符,用来定义互联网上一个唯一的资源 例如:一张图片、一个文件、一段视频都可以用 url 唯一确定
加载一个网页,通常都是先加载 document 文档,
在解析 document 文档的时候,遇到链接,则针对超链接发起下载图片的请求。

3.1.3. 请求头

User-agent:请求头中如果没有 user-agent 客户端配置,服务端可能将你当做一个非法用户 host;
cookies:cookie 用来保存登录信息
注意: 一般做爬虫都会加上请求头
在这里插入图片描述
请求头需要注意的参数:
(1)Referrer:访问源至哪里来(一些大型网站,会通过 Referrer 做防盗链策略;所有爬虫也要注意模拟)
(2)User-Agent:访问的浏览器(要加上否则会被当成爬虫程序)
(3)cookie:请求头注意携带

3.1.4. 请求体

如果是 get 方式,请求体没有内容 (get 请求的请求体放在 url 后面参数中,直接能看到)
如果是 post 方式,请求体是 format data
ps:
1、登录窗口,文件上传等,信息都会被附加到请求体内
2、登录,输入错误的用户名密码,然后提交,就可以看到 post,正确登录后页面通常会跳转,无法捕捉到 post

3.2. 爬虫响应

3.2.1. 响应状态码

200:代表成功
  301:代表跳转
  404:文件不存在
  403:无权限访问
  502:服务器错误

3.2.2. respone header

响应头需要注意的参数:
1、Set-Cookie:BDSVRTM=0; path=/:可能有多个,是来告诉浏览器,把 cookie 保存下来
2、Content-Location:服务端响应头中包含 Location 返回浏览器之后,浏览器就会重新访问另一个页面

3.2.3. preview 就是网页源代码

JSON 数据
如网页 html、图片、二进制数据等

4. 基础爬虫开发

4.1. 爬虫实例1

以下是一个基础的 Python 爬虫示例,用于爬取百度热搜榜的内容:

import requests
from bs4 import BeautifulSoup# 发送HTTP请求
url = "https://top.baidu.com/board?tab=realtime"
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"}
response = requests.get(url, headers=headers)# 检查请求是否成功
if response.status_code == 200:# 解析HTML内容soup = BeautifulSoup(response.text, 'html.parser')# 提取热搜标题hot_titles = soup.select("div.c-single-text-ellipsis")for i, title in enumerate(hot_titles, 1):print(f"{i}. {title.text.strip()}")
else:print(f"请求失败,状态码: {response.status_code}")

这个示例中我们使用 requests 库对百度热搜榜发起 HTTP 请求,获取页面的 HTML 内容。
然后利用 BeautifulSoup 库(这是一个强大的 HTML 解析工具,后续博客会详细介绍)对获取的内容进行解析。通过选择器定位到热搜标题所在的元素(具有"c-single-text-ellipsis"类的 div 元素),我们能够准确提取出当前的热搜话题,并按顺序打印出来。代码中还添加了请求头信息和错误处理机制,确保爬取过程更加稳定可靠。
在这里插入图片描述
在这里插入图片描述

4.2. 爬虫实例2

参考:https://cloud.tencent.com/developer/article/1934685
尚未测试

4.2.1. 单线程版

import re
import requests
import hashlib
import time# respose=requests.get('http://www.xiaohuar.com/v/')
# # print(respose.status\_code)# 响应的状态码
# # print(respose.content)  #返回字节信息
# # print(respose.text)  #返回文本内容
# urls=re.findall(r'class="items".\*?href="(.\*?)"',respose.text,re.S)  #re.S 把文本信息转换成1行匹配
# url=urls\[5\]
# result=requests.get(url)
# mp4\_url=re.findall(r'id="media".\*?src="(.\*?)"',result.text,re.S)\[0\]
#
# video=requests.get(mp4\_url)
#
# with open('D:\\\\a.mp4','wb') as f:
#     f.write(video.content)
#def get_index(url):respose = requests.get(url)if respose.status_code==200:return respose.textdef parse_index(res):urls = re.findall(r'class="items".\*?href="(.\*?)"', res,re.S)  # re.S 把文本信息转换成1行匹配return urlsdef get_detail(urls):for url in urls:if not url.startswith('http'):url = 'http://www.xiaohuar.com%s' %urlresult = requests.get(url)if result.status_code==200 :mp4_url_list = re.findall(r'id="media".\*?src="(.\*?)"', result.text, re.S)if mp4_url_list:mp4_url = mp4_url_list[0]print(mp4_url)# save(mp4\_url)def save(url):video = requests.get(url)if video.status_code==200:m = hashlib.md5()m.updata(url.encode('utf-8'))m.updata(str(time.time()).encode('utf-8'))filename = r'%s.mp4'% m.hexdigest()filepath = r'D:\\\\%s'%filenamewith open(filepath, 'wb') as f:f.write(video.content)def main():for i in range(5):res1 = get_index('http://www.xiaohuar.com/list-3-%s.html'% i )res2 = parse_index(res1)get_detail(res2)if __name__ == '__main__':main()

4.2.2. 多线程版

import re
import requests
import hashlib
import timefrom concurrent.futures import ThreadPoolExecutor
p = ThreadPoolExecutor(30) #创建1个程池中,容纳线程个数为30个;def get_index(url):respose = requests.get(url)if respose.status_code==200:return respose.textdef parse_index(res):res = res.result() # 进程执行完毕后,得到1个对象urls = re.findall(r'class="items".\*?href="(.\*?)"', res,re.S)  # re.S 把文本信息转换成1行匹配for url in urls:p.submit(get_detail(url))  #获取详情页 提交到线程池def get_detail(url):  # 只下载1个视频if not url.startswith('http'):url = 'http://www.xiaohuar.com%s' % urlresult = requests.get(url)if result.status_code==200 :mp4_url_list = re.findall(r'id="media".\*?src="(.\*?)"', result.text, re.S)if mp4_url_list:mp4_url=mp4_url_list[0]print(mp4_url)# save(mp4_url)def save(url):video = requests.get(url)if video.status_code==200:m = hashlib.md5()m.updata(url.encode('utf-8'))m.updata(str(time.time()).encode('utf-8'))filename = r'%s.mp4'% m.hexdigest()filepath = r'D:\\\\%s'%filenamewith open(filepath, 'wb') as f:f.write(video.content)def main():for i in range(5):p.submit(get_index, 'http://www.xiaohuar.com/list-3-%s.html'% i).add_done_callback(parse_index)# 1、先把爬主页的任务(get_index)异步提交到线程池# 2、get_index 任务执行完后,会通过回调函 add_done_callback() 数通知主线程,任务完成;# 2、把 get_index 执行结果(注意线程执行结果是对象,调用 res=res.result() 方法,才能获取真正执行结果),当做参数传给 parse_index# 3、parse_index 任务执行完毕后,# 4、通过循环,再次把获取详情页 get_detail() 任务提交到线程池执行if __name__ == '__main__':main()
http://www.xdnf.cn/news/9111.html

相关文章:

  • ViT- an image is worth 16x16 words- transformers for image recognition at scale
  • YOLOv11改进 | Neck篇 | 双向特征金字塔网络BiFPN助力YOLOv11有效涨点
  • Python学习笔记--Django 表单处理
  • Django orm详解--组成部件
  • 限制 SSH 访问仅允许特定 IP 连接
  • 基于线性回归的短期预测
  • SAST国标分析︱灵脉AI深度兼容GB/T 34943/34944-2017源代码漏洞测试规范
  • LINUX526 回顾 配置ssh rsync定时备份(未完成)
  • OpenCV CUDA模块图像过滤------创建一个 Scharr 滤波器函数createScharrFilter()
  • 第12次04 :首页展示用户名
  • 数据仓库维度建模详细过程
  • 频繁报FTPResponse 421 received.Server closed connection
  • 1. 数据结构
  • 《软件工程》第 8 章 - 人机交互设计
  • QML设计登录界面
  • 基于FPGA的IIC多通道选择器(IIC Switch/Bridge)
  • Qt popup窗口半透明背景
  • mac for vscode集成的源代码管理 撤销和删除文件报错Permission denied
  • 【Macos】安装前端环境rust+node环境
  • 从界面设计到设备互联:基于Qt的ARM Linux自动化控制面板开发全解析
  • 【图像处理基石】什么是色彩模式?
  • 深度学习在建筑物提取中的应用综述
  • 【Qt开发】输入类控件
  • C语言初阶--结构体
  • 高性能排行榜系统架构实战
  • 解码词向量:让AI语言模型更透明
  • Leetcode 3563. Lexicographically Smallest String After Adjacent Removals
  • 基于Flask实现当当网书籍数据分析大屏
  • 清除谷歌浏览器中的“您的浏览器由所属组织/贵单位管理”
  • 《软件工程》第 2 章 -UML 与 RUP 统一过程