数据采集基础:爬虫基本原理、Requests库入门、BeautifulSoup解析HTML
各位同学好,今天我们来聊聊数据采集这块硬骨头。做舆情监控,说白了第一步就是「怎么把数据拿回来」。我刚开始接触爬虫那会儿,总觉得这东西很神秘,后来发现,其实就是模拟浏览器去访问网页,然后把内容拆开、提取、存起来。嗯,就这么简单。
核心一句话:爬虫 = 模拟请求 + 解析响应 + 提取数据。
爬虫的基本原理
爬虫的本质是什么?你想想看,你在浏览器里输入网址,回车,页面出来了。爬虫做的就是这件事——只不过是用代码代替了鼠标和键盘。
一个完整的爬虫流程,我习惯把它拆成三步:
- 发送请求:用代码向目标服务器说「嘿,把页面给我」。
- 获取响应:服务器返回HTML、JSON或者别的格式数据。
- 解析提取:从返回的数据里,把我们想要的信息抠出来。
我在项目中遇到过一个问题:有些网站会检测你是不是真人。比如频繁请求会被封IP,或者需要处理Cookie。这些坑,后面我会一个个说。
注意:爬虫不是万能的。有些网站有反爬机制,比如验证码、IP限制、User-Agent检测。做舆情监控,一定要遵守网站的robots.txt协议,别把自己搞进黑名单。
下面这张图,是我自己总结的爬虫核心流程,你一看就明白:
Requests库入门
Python里做网络请求,Requests库是首选。为什么?因为它够简单、够直观。我最早用urllib的时候,写个POST请求要好几行,换了Requests之后,一行搞定。
先安装:
pip install requests
然后看个最简单的例子——拿百度首页:
import requests
url = "https://www.baidu.com"
response = requests.get(url)
print(response.status_code) # 200 表示成功
print(response.text[:500]) # 打印前500个字符
跑一下,你会看到一堆HTML代码。这就是服务器给你的原始响应。
小技巧:我习惯在请求时加个headers参数,模拟浏览器访问。不然有些网站直接返回403。
加headers的写法:
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}
response = requests.get(url, headers=headers)
为什么会这样?因为服务器会检查请求头,如果发现你是「爬虫」,直接拒绝。加个常见的浏览器User-Agent,就能蒙混过关。
Requests还支持POST、PUT、DELETE等方法。做舆情监控,最常用的是GET和POST。比如模拟登录时,就得用POST提交表单数据:
data = {"username": "admin", "password": "123456"}
response = requests.post("https://example.com/login", data=data)
我曾经踩过一个坑:某个网站返回的数据是压缩过的,直接打印出来全是乱码。后来发现加个 response.encoding = 'utf-8' 就解决了。嗯,这里要注意,有时候服务器返回的编码和页面实际编码不一致,手动指定一下更稳妥。
BeautifulSoup解析HTML
拿到HTML之后,怎么把我们需要的信息提取出来?手动正则匹配?太累了,而且容易出错。BeautifulSoup就是干这个的——把HTML变成一棵树,然后按标签、类名、ID去摘叶子。
安装:
pip install beautifulsoup4
基本用法:
from bs4 import BeautifulSoup
html = "<html><body><h1>Hello World</h1><p class='content'>这是正文</p></body></html>"
soup = BeautifulSoup(html, 'html.parser')
# 提取h1标签
h1 = soup.find('h1')
print(h1.text) # 输出:Hello World
# 提取class为content的p标签
p = soup.find('p', class_='content')
print(p.text) # 输出:这是正文
你看,就这么简单。find()返回第一个匹配的标签,find_all()返回所有匹配的列表。
实际项目中,我经常这样用:
# 假设我们要爬取新闻标题
news_list = soup.find_all('h2', class_='news-title')
for news in news_list:
title = news.text.strip()
link = news.find('a')['href']
print(f"标题:{title},链接:{link}")
重点:BeautifulSoup支持多种解析器。默认的html.parser够用,但遇到复杂HTML时,我推荐用lxml,速度更快、容错性更好。
安装lxml:
pip install lxml
使用时改成:
soup = BeautifulSoup(html, 'lxml')
BeautifulSoup还支持CSS选择器,这个我特别喜欢。比如:
# 用CSS选择器提取所有class为item的div
items = soup.select('div.item')
for item in items:
print(item.text)
我个人习惯是:简单的用find/find_all,复杂的用select。你想想看,如果嵌套层级很深,写一串find链式调用多累,CSS选择器一行搞定。
实战:爬取一个简单的新闻列表
光说不练假把式。我们拿一个真实的例子来演示——假设要爬取某个新闻网站的头条列表。
import requests
from bs4 import BeautifulSoup
url = "https://example-news.com"
headers = {"User-Agent": "Mozilla/5.0"}
response = requests.get(url, headers=headers)
soup = BeautifulSoup(response.text, 'lxml')
# 假设头条新闻都在class为headline的div里
headlines = soup.select('div.headline h2 a')
for headline in headlines:
title = headline.text.strip()
link = headline['href']
print(f"{title} -> {link}")
跑完这段代码,你就能拿到所有头条的标题和链接。这就是舆情监控的第一步——把数据从网页上「薅」下来。
避坑指南:我曾经遇到过一个网站,它的HTML结构会动态变化。今天用class="title",明天改成class="heading"。解决方案是:不要死磕一个选择器,多观察页面结构,或者用更通用的匹配规则。
总结一下
今天的内容,说白了就是三件事:
- 爬虫原理:请求-响应-解析,循环翻页。
- Requests库:发请求、拿响应、加headers伪装。
- BeautifulSoup:解析HTML、提取数据、用选择器定位。
这些是数据采集的基石。后面我们会讲更高级的东西,比如处理动态页面、应对反爬、分布式采集等等。但今天这些,你必须练熟。
嗯,回去之后自己动手写个爬虫,爬一下你常看的新闻网站。遇到问题很正常,多调试几次就通了。