
适合人群完全没有爬虫经验的初学者 ️ 涉及工具Python 3、requests、BeautifulSoup4、浏览器开发者工具 学习目标看懂网页本质 → 发送请求 → 解析数据 → 批量爬取一、爬虫到底是什么先看大图景在写任何代码之前先建立整体认知。所谓网络爬虫本质上是模拟浏览器向服务器发送请求获取网页内容然后从中提取我们想要的数据。整个流程可以拆成三步这也是几乎所有爬虫的灵魂框架plain① 获取网页内容 —— 向服务器要数据服务器把网页源代码返回给我们 ↓ ② 解析网页内容 —— 从一大堆 HTML 代码里精准找到想要的数据 ↓ ③ 存储 / 分析数据 —— 存成表格Excel/CSV、做数据分析、画可视化图表对应到你的学习笔记就是获取 → 解析 → 存储分析。二、前置知识一HTTP协议爬虫的地基2.1 什么是HTTPHTTPHypertext Transfer Protocol超文本传输协议是客户端浏览器和服务器之间的请求-响应协议。你每打开一个网页背后都在发生一次对话浏览器服务器你好我要/movie/top250这个页面的内容 服务器好的给你返回网页代码爬虫的第一步就是用代码代替浏览器去完成这个对话。2.2 HTTP请求的结构一个HTTP请求由三部分组成1请求行POST /user/info?new_usertrue HTTP/1.1POST请求方法常见的还有GET/user/info?new_usertrue资源路径 查询参数HTTP/1.1协议版本还有 0.9、1.0、2.0 等2请求头HeadersHost: www.example.com User-Agent: curl/7.77.0 Accept: */*请求头是关于请求的附加信息。其中User-Agent用户代理告诉服务器我是谁。⚠️关键点来了如果不加User-Agent服务器看到的就是一个裸奔的程序很可能直接拒绝你比如豆瓣会返回418 错误。解决办法是伪装成浏览器headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) }3请求体BodyPOST请求通常带有数据比如登录时提交账号密码格式常见为 JSON{ username: zhangsan, email: zhangsanexample.com }2.3 GET 和 POST 的区别面试高频表格对比项GETPOST用途获取数据创建/提交数据场景浏览网页、翻页提交账号、注册表单参数位置拼在URL里?keyvalue放在请求体里爬虫常用度⭐⭐⭐⭐⭐⭐⭐plain# GET请求参数直接写在URL上 www.douban.com/movie/top250?start75filterunwatched └─────┬─────┘ 问号后面就是查询参数2.4 HTTP响应的结构服务器返回的响应同样由三部分组成HTTP/1.1 200 OK ← 状态行 Date: Fri, 27 Jan 2023 02:10:48 GMT Content-Type: text/html; charsetutf-8 ← 响应头 !DOCTYPE html html headtitle首页/title/head bodyh1Hello World/h1/body /html ← 响应体真正的网页内容状态行协议版本 状态码 状态消息响应头比如Content-Type告诉我们返回内容的格式是text/html响应体就是我们要爬的 HTML 源码2.5 常见状态码务必背下来状态码含义✅ 200 OK请求成功最理想↪️ 301 Moved Permanently资源永久移动到新地址⚠️ 400 Bad Request客户端请求不能被服务器理解⚠️ 401 Unauthorized请求未经授权⚠️ 403 Forbidden服务器拒绝提供服务反爬常见⚠️ 404 Not Found请求的资源不存在❌ 500 Internal Server Error服务器内部错误❌ 503 Server Unavailable服务器当前无法处理请求在代码中用response.status_code查看用response.ok快速判断是否成功2xx 返回 True。三、前置知识二HTML网页结构解析的地图3.1 网页三大件技术作用HTML定义网页的结构和信息骨架CSS定义网页的样式皮肤JavaScript定义网页的行为和交互逻辑肌肉爬虫主要和 HTML 打交道。3.2 HTML的基本结构html body h1这是一个标题/h1 p这是一个段落/p /body /htmlHTML 由一对一对的标签tag组成标签名开始/标签名结束。h1和p是兄弟标签同级关系。3.3 常用标签速查标签含义h1~h6标题1最大6最小p段落br换行i斜体u下划线a链接div区块容器最常用页面布局ul/ol/li无序列表 / 有序列表 / 列表项span行内容器常用来包裹小片段文字b/strong加粗table/tr/td表格 / 表格行table row/ 单元格thead/tbody表头区 / 表体区以表格为例完整结构长这样table thead tr td表头1/td td表头2/td /tr /thead tbody tr td111/td td222/td /tr tr td333/td td444/td /tr /tbody /table爬虫提数据的核心思路数据总是藏在某个标签里我们要做的就是在 HTML 中找到那个标签把它抠出来。四、实战第一步requests库获取网页内容4.1 安装与导入pip install requestsimport requests4.2 第一个爬虫获取books.toscrape.com首页import requests response requests.get(http://books.toscrape.com/) if response.ok: print(response.text) else: print(请求失败)到这一步你就已经完成了爬虫流程里的第一步——拿到了网页的源代码一大串HTML文本。4.3 response对象的常用属性response requests.get(http://books.toscrape.com/) print(response) # 打印响应对象本身 print(response.status_code) # 状态码200表示成功 print(response.text) # 响应体内容字符串形式 print(response.headers) # 响应头 print(response.ok) # 是否成功2xx → True4.4 反爬入门伪装User-Agent直接爬豆瓣 Top250 会遇到 418我是茶壶说明服务器识破了你import requests response requests.get(https://movie.douban.com/top250) print(response) # Response [418] 被识破了加 headers 伪装成浏览器import requests headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) } response requests.get(https://movie.douban.com/top250, headersheaders) print(response.status_code) # 200成功 print(response.text) 记忆口诀先不加 headers 试试不行就加 User-Agent还不行就检查 Cookie、Referer 等。五、实战第二步BeautifulSoup解析网页内容获取到的response.text是一大坨字符串肉眼找数据是不可能的。我们用BeautifulSoup把它变成一个结构化、可查询的对象。5.1 安装与导入pip install beautifulsoup4from bs4 import BeautifulSoup import requests5.2 三步走请求 → 做汤 → 找料from bs4 import BeautifulSoup import requests # 1. 请求网页 content requests.get(http://books.toscrape.com/).text # 2. 把字符串熬成汤解析成结构化对象 soup BeautifulSoup(content, html.parser)经过BeautifulSoup处理后得到的soup对象就拥有了非常多的方法和属性可以像查字典一样查找标签。5.3 findAll()批量查找标签# 按标签名查找找到所有 p 标签 all_prices soup.findAll(p, attrs{class: price_color}) for price in all_prices: print(price.string[2:])运行结果51.77 53.74 50.10 47.82 54.23 ...逐行拆解这个方法soup.findAll(p, attrs{class: price_color})找到所有class 为price_color的p标签返回一个列表price.string取标签里的文本内容如£51.77[2:]字符串切片去掉前2个字符£留下纯数字 注意区分find()→ 找第一个返回单个对象findAll()→ 找所有返回列表5.4 案例提取书名在 books.toscrape 上书名藏在h3标签里的a标签中h3 a hrefcatalogue/a-light-in-the-attic_1000/index.html titleA Light in the AtticA Light in the .../a /h3对应代码all_titles soup.findAll(h3) for title in all_titles: all_links title.findAll(a) for link in all_links: print(link.string) # 通过string属性拿到标签内的文本输出A Light in the ... Tipping the Velvet Soumission Sharp Objects Sapiens: A Brief History ... ...嵌套查找是很常用的技巧先找大容器h3再在容器内部继续找小标签a。5.5 案例爬豆瓣Top250电影名先在浏览器里右键 → 检查审查元素找到标题对应的标签span classtitle三傻大闹宝莱坞/span对应代码import requests from bs4 import BeautifulSoup headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) } response requests.get(https://movie.douban.com/top250, headersheaders) html response.text soup BeautifulSoup(html, html.parser) all_titles soup.findAll(span, attrs{class: title}) for title in all_titles: title_string title.string # 豆瓣每部电影有中文名和英文名两个title用/判断过滤 if / not in title_string: print(title_string)这里用了一个细节技巧if / not in title_string——因为每部电影的中文名和英文名都是classtitle通过是否包含/来只保留中文名。六、实战第三步翻页爬取全部250部电影豆瓣Top250每页只有25部URL规律是第1页: https://movie.douban.com/top250?start0 第2页: https://movie.douban.com/top250?start25 第3页: https://movie.douban.com/top250?start50 ...规律是start每次加 25。用range(0, 250, 25)生成翻页参数for start_num in range(0, 250, 25): print(start_num) # 输出: 0, 25, 50, 75, 100, 125, 150, 175, 200, 225完整代码import requests from bs4 import BeautifulSoup headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) } for start_num in range(0, 250, 25): response requests.get( fhttps://movie.douban.com/top250?start{start_num}, headersheaders ) html response.text soup BeautifulSoup(html, html.parser) all_titles soup.findAll(span, attrs{class: title}) for title in all_titles: title_string title.string if / not in title_string: print(title_string)️善意提醒实际爬取时建议在循环中加入time.sleep(1~3)降低请求频率避免对目标网站造成压力。七、爬虫法律与道德红线重要笔记里总结的三条底线必须刻进DNA不要爬取公民隐私数据要尊重版权保护的内容国家事务、国防建设相关网站绝对不碰技术层面的注意点⚡请求频率不能过高否则无异于DDoS 攻击通过给服务器发送海量高频请求让网站资源被耗尽无法服务其他正常用户网站如果做出明显的反爬限制如有些内容登录后可看尊重限制机制不要强行突破 爬取前查看网站的robots.txt文件如www.example.com/robots.txt它声明了允许/禁止爬取的网页路径范围八、完整知识图谱复习用┌─────────────────────────────────────────┐ │ 爬虫三步走 │ ├──────────────┬──────────────────────────┤ │ ① 获取网页内容 │ requests库 │ │ │ · requests.get(网址) │ │ │ · response.status_code │ │ │ · response.text / .ok │ │ │ · headers伪装User-Agent │ ├──────────────┼──────────────────────────┤ │ ② 解析网页内容 │ BeautifulSoup库 │ │ │ · BeautifulSoup(text, │ │ │ html.parser) │ │ │ · find() / findAll() │ │ │ · attrs{class: ...} │ │ │ · .string 取文本 │ │ │ · 切片 [2:] 清洗数据 │ ├──────────────┼──────────────────────────┤ │ ③ 存储/分析 │ 存CSV/Excel → 数据分析 │ │ │ → 可视化图表 │ └──────────────┴──────────────────────────┘ 底层支撑 HTTP协议请求行/请求头/请求体状态行/响应头/响应体 HTML结构标签、class属性、层级与兄弟关系最小可运行模板背下来90%的简单爬虫都是它的变体import requests from bs4 import BeautifulSoup headers {User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)} url 目标网址 response requests.get(url, headersheaders) if response.ok: soup BeautifulSoup(response.text, html.parser) items soup.findAll(标签名, attrs{class: 目标class}) for item in items: print(item.string) else: print(请求失败:, response.status_code)九、常见问题速查FAQQ1为什么返回418 / 403服务器识别出你是爬虫。加上headers伪装 User-Agent必要时补充 Cookie、Referer。Q2为什么findAll返回空列表检查 class 名是否写对浏览器里右键检查确认注意有的class有多个值要用完整字符串匹配。Q3price.string报错 NoneType说明该标签内嵌套了子标签string无法确定取哪个。改用.get_text()。Q4中文乱码尝试response.encoding response.apparent_encoding后再取.text。十、写在最后零基础学爬虫其实就两条主线网络线理解HTTP请求-响应 → 用requests发请求解析线理解HTML标签结构 → 用BeautifulSoup查标签把这两条线打通再加一个for循环实现翻页你就已经具备了爬取绝大多数静态网页的能力。下一步可以进阶学习数据存储CSV/Excel/MySQL、XPath、正则表达式、Selenium动态页面爬取、Scrapy框架。如果觉得本文对你有帮助欢迎点赞收藏复习时直接对照第八节的图谱过一遍即可。评论区欢迎交流爬取中遇到的问题下期预告《Python爬虫进阶数据存储与清洗实战》。