ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

python爬虫要用到的库总结

python爬虫要用到的库总结 前言很多人一上手就问「爬虫要装哪几个库」然后照着某篇清单把 requests、BeautifulSoup、lxml、Scrapy、selenium 全装上结果一个也没用明白。库不是越多越好关键是搞清楚每一类库解决的是哪一步的问题有的负责发请求有的负责解析 HTML有的负责调度和去重有的专门对付 JavaScript 渲染的页面。另一个常见误解是把标准库当成「玩具」。事实上urllib.request能发完整的 HTTP 请求html.parser能可靠地遍历标签urllib.robotparser能解析 robots.txtjson、csv、sqlite3、re、gzip、concurrent.futures覆盖了存取、清洗和并发。一个不需要安装任何依赖的爬虫是真实可用的。需要提前声明本文涉及第三方库时只讲它们在流程里的定位和大致用法具体参数名和返回类型请以各库官方文档为准。因为环境里没有安装这些库任何具体到参数名的调用都不应被当作可直接照抄的成品。另外Python 2 已于 2020 年 1 月 1 日停止维护本文一律用 Python 3 写法。一、标准库一行安装命令都不需要标准库适合「抓取量不大、页面是服务端渲染、能自己控制流程」的场景。它最大的价值是零依赖、可移植、行为稳定。# 适用于 Python 3.8import urllib.requestimport urllib.parseimport urllib.errorimport urllib.robotparserimport http.clientimport gzipimport jsonimport csvimport sqlite3import reimport timeimport concurrent.futuresprint(标准库导入完成无需 pip 安装)模块负责的环节典型用途urllib.request发请求urlopen、Request设置请求头urllib.parseURL 处理urljoin拼相对地址、urlencode编码查询串urllib.error异常区分HTTPError带状态码与URLErrorurllib.robotparser合规解析 robots.txtcan_fetch判断http.client底层 HTTP需要精细控制连接时用html.parser解析 HTML事件驱动覆写handle_starttag等回调json/csv存数据读写 JSON、CSVsqlite3存数据单文件数据库天然适合去重和增量re文本清洗从已取出的文本里抠日期、数字gzip解压处理Content-Encoding: gzip的响应concurrent.futures并发线程池处理 I/O 密集抓取注意re的位置它适合清洗已经抽出来的纯文本不适合直接套在整页 HTML 上。HTML 的嵌套和属性顺序不是正则能稳定描述的。二、第三方 HTTP 客户端requests / httpx / aiohttp标准库的urllib.request能用但接口偏底层编码要自己解、会话连接复用要自己配、超时和重试要自己写。这类库的价值就是把这些样板收起来。requests同步、接口直观是事实上的入门首选。它的定位是「给人用的 HTTP 客户端」会话复用用Session请求参数、表单、JSON 都有对应入口。具体参数以 requests 官方文档为准。httpx接口风格接近 requests同时提供同步和异步两套 API适合既要简单又要异步的场景。aiohttpasyncio生态里的 HTTP 客户端异步抓取大量页面时常用。它与asyncio事件循环绑定写法与同步库差别较大。这里只给出定位不给出具体调用——因为记不准参数名而写一个「看起来对」的签名比不写更危险。需要时请查对应库的官方文档。三、解析库BeautifulSoup / lxml / html.parser解析层解决的是「从 HTML 里把字段抠出来」。选择取决于页面是否规整、你更习惯 CSS 选择器还是 XPath。html.parser标准库容错性尚可事件驱动。适合结构简单或需要边下边解析的场景。BeautifulSoup在某个底层解析器之上提供统一的树形接口容错性强对残缺 HTML 友好。用 CSS 选择器取元素很方便。以 BeautifulSoup 官方文档为准。lxml底层用 libxml2解析快、支持 XPath。缺点是它是 C 扩展安装依赖较多。浏览器自动化selenium / playwright页面内容由 JavaScript 动态渲染时才需要。代价是慢、重只在确实必要且目标站允许时使用。一个务实的原则能用服务端渲染的静态 HTML 解决的就不要上浏览器自动化。四、工程化框架Scrapy当抓取规模变大你要处理的就不只是「抓一个页面」而是调度、去重、限速、失败重试、数据管道。这类需求由爬虫框架承担。Scrapy是最常见的 Python 爬虫框架把「引擎、调度器、下载器、爬虫、管道」拆成独立组件用Request/Response和回调callback组织解析流程。适合规则明确、站点多、需要长期运行的采集任务如果只是抓几十个页面用它反而是过度设计。调度与存储层面还会用到 Redis、消息队列、关系型数据库等通用组件它们不是爬虫专用库这里只提定位。实战只用标准库搭一个抓取小工具下面这段不依赖任何第三方库演示「请求—解码—解析—存库」这条链路的骨架。把数据落到 sqlite3顺便用主键天然去重。# 适用于 Python 3.8import sqlite3import timeimport urllib.errorimport urllib.requestfrom html.parser import HTMLParserclass PageTitleScanner(HTMLParser):def __init__(self):super().__init__(convert_charrefsTrue)self.in_title Falseself.title_parts []def handle_starttag(self, tag, attrs):if tag title:self.in_title Truedef handle_endtag(self, tag):if tag title:self.in_title Falsedef handle_data(self, data):if self.in_title:self.title_parts.append(data)def title(self):return .join(self.title_parts).strip()def fetch_title(url, timeout10):req urllib.request.Request(url, headers{User-Agent: LibSummaryBot/0.1 (contact: meexample.com),})with urllib.request.urlopen(req, timeouttimeout) as resp:raw resp.read()charset resp.headers.get_content_charset() or utf-8text raw.decode(charset, errorsreplace)parser PageTitleScanner()parser.feed(text)parser.close()return parser.title()def main():urls [https://www.example.com/, https://www.example.org/]conn sqlite3.connect(titles.db)conn.execute(CREATE TABLE IF NOT EXISTS pages (url TEXT PRIMARY KEY, title TEXT))for url in urls:try:title fetch_title(url)except urllib.error.HTTPError as e:print(HTTP 错误, e.code, url)continueexcept urllib.error.URLError as e:print(网络错误, e.reason, url)continueconn.execute(INSERT OR REPLACE INTO pages (url, title) VALUES (?, ?),(url, title),)conn.commit()print(已保存:, url, -, title)time.sleep(1) # 限速conn.close()if __name__ __main__:main()INSERT OR REPLACE配合url主键同一地址重复抓到也只保留一条比手工维护去重集合更省事。常见坑点先装库再想需求❌ 一次性装上 requests、Scrapy、selenium却不知道该用哪层。 ✅ 先明确页面是否需要 JS 渲染、规模多大再按「请求—解析—调度」分层选库。把re当成 HTML 解析器❌re.findall(ra href(.*?), html)—— 属性顺序、单双引号、换行一变就漏。 ✅ 用html.parser、BeautifulSoup 或 lxml 做结构解析re只清洗抽出的纯文本。用第三方库却硬记参数名❌ 凭印象写一个「看起来合理」的调用参数名或顺序其实是错的。 ✅ 记不准就只写用法思路以该库官方文档为准。html.parser子类忘记调用父类构造❌def __init__(self): self.links []—— 不解构内部状态feed()会出问题。 ✅ 先super().__init__(convert_charrefsTrue)再初始化自己的属性。硬编码 UTF-8 解码第三方库返回的内容❌ 拿到 bytes 就.decode(utf-8)GBK 页面直接乱码。 ✅ 先取响应头的 charset取不到再退回 UTF-8 并加errorsreplace。忽略 gzip 压缩❌ 直接解码响应体得到一堆二进制乱码。 ✅ 检查Content-Encoding用gzip模块解压后再解码。把iteritems()/xrange当成还能用的写法❌for k, v in d.iteritems():、for i in xrange(10):—— Python 3 均已移除。 ✅ 用d.items()返回视图、range本身就是惰性的。上多线程就以为能提速❌ CPU 密集任务用ThreadPoolExecutor指望加速。 ✅ 爬虫主要受 I/O 限制线程池有意义CPU 密集要换多进程。总结层次标准库方案第三方方案何时升级发请求urllib.requestrequests / httpx / aiohttp需要会话、重试、异步时解析 HTMLhtml.parserBeautifulSoup / lxml页面复杂、要 XPath/CSS 时渲染 JS无selenium / playwright内容确实由 JS 生成时调度工程化自己写循环Scrapy站点多、需长期运行时存储sqlite3/json/csv数据库、消息队列数据量大、要并发写时选库的顺序应该是「先让标准库跑通再按瓶颈补库」。绝大多数入门任务标准库就够了真正需要第三方库的时候你已经能说清自己缺的是哪一步。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表