news 2026/7/23 3:28:16

python爬虫基础实战案例

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
python爬虫基础实战案例

文章目录

    • 1 实战一:爬取豆瓣Top250图书信息
      • 目标分析
      • 完整代码
    • 2 实战二:批量下载图片
      • 关键技巧
      • 多线程加速下载
    • 3 实战三:爬取表格数据并存入Excel
      • 安装依赖
      • 爬取天气历史数据
    • 4 完整项目:知乎热榜数据采集

下面通过几个经典案例把前面的知识串联起来。包含三类实战项目:静态页面爬取、图片批量下载、表格数据提取与存储。每个案例都有完整代码,可以直接运行。

1 实战一:爬取豆瓣Top250图书信息

豆瓣图书是学习爬虫的经典案例,页面结构清晰,适合练习CSS选择器和数据存储。

目标分析

目标:爬取豆瓣Top250图书的书名、作者、评分、出版信息、评价人数,保存为CSV文件。

打开F12,分析页面结构:

  • 每本书在div.item容器中
  • 书名在span.title
  • 评分在span.rating_num
  • 作者和出版信息在p标签中
  • 翻页链接在a标签,URL参数为?start=0,25,50...

完整代码

importrequestsfrombs4importBeautifulSoupimportcsvimporttimeimportrandomdefget_headers():"""返回伪装请求头"""return{'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36','Accept-Language':'zh-CN,zh;q=0.9'}defparse_book_list(html):"""解析单页图书列表"""soup=BeautifulSoup(html,'lxml')books=[]foriteminsoup.select('div.item'):# 书名(有时会有副标题)title_tags=item.select('span.title')title=title_tags[0].text.strip()iftitle_tagselse'未知'# 评分rating_tag=item.select_one('span.rating_num')rating=rating_tag.text.strip()ifrating_tagelse'0'# 评价人数inq_tag=item.select_one('span.inq')inq=inq_tag.text.strip()ifinq_tagelse''# 作者/出版信息info_tag=item.select_one('div.bd p')info=info_tag.text.strip().replace('\n',' ')ifinfo_tagelse''# 排名rank_tag=item.select_one('em')rank=rank_tag.textifrank_tagelse''books.append({'rank':rank,'title':title,'rating':rating,'inq':inq,'info':info})returnbooksdefcrawl_douban_books():"""爬取豆瓣图书Top250"""all_books=[]base_url='https://book.douban.com/top250'forstartinrange(0,250,25):url=f'{base_url}?start={start}'print(f'爬取第{start//25+1}页:{url}')try:response=requests.get(url,headers=get_headers(),timeout=10)response.raise_for_status()books=parse_book_list(response.text)all_books.extend(books)print(f'本页提取{len(books)}本书')exceptExceptionase:print(f'爬取失败:{e}')# 随机延时 1-3 秒,避免被封time.sleep(random.uniform(1,3))returnall_booksdefsave_to_csv(books,filename='douban_books.csv'):"""保存为CSV文件"""ifnotbooks:print('没有数据可保存')returnwithopen(filename,'w',encoding='utf-8-sig',newline='')asf:fieldnames=['rank','title','rating','inq','info']writer=csv.DictWriter(f,fieldnames=fieldnames)writer.writeheader()writer.writerows(books)print(f'已保存{len(books)}条数据至{filename}')if__name__=='__main__':books=crawl_douban_books()save_to_csv(books)# 打印前5条预览forbookinbooks[:5]:print(f'[{book["rank"]}]{book["title"]}-{book["rating"]}分')

2 实战二:批量下载图片

批量下载图片是爬虫的常见需求。这个案例演示如何下载图片并保存到本地。

关键技巧

图片是二进制数据,需要用response.content获取,而不是response.text

importrequestsimportosimporttimeimportrandomfrompathlibimportPathfromurllib.parseimporturlparsedefdownload_image(url,save_path,headers=None):"""下载单张图片"""try:response=requests.get(url,headers=headers,timeout=15,stream=True)response.raise_for_status()# 检查是否是图片类型content_type=response.headers.get('Content-Type','')if'image'notincontent_type:print(f'不是图片类型:{content_type}')returnFalse# 从URL中获取文件名parsed_url=urlparse(url)filename=os.path.basename(parsed_url.path)ifnotfilenameor'.'notinfilename:filename=f'image_{int(time.time())}.jpg'# 保存图片full_path=os.path.join(save_path,filename)withopen(full_path,'wb')asf:forchunkinresponse.iter_content(chunk_size=8192):f.write(chunk)file_size=os.path.getsize(full_path)print(f'下载成功:{filename}({file_size/1024:.1f}KB)')returnTrueexceptExceptionase:print(f'下载失败{url}:{e}')returnFalsedefbatch_download_images(image_urls,save_dir='images'):"""批量下载图片"""# 创建保存目录Path(save_dir).mkdir(parents=True,exist_ok=True)headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64)','Referer':'https://example.com'# 防盗链处理}success_count=0fail_count=0fori,urlinenumerate(image_urls,1):print(f'[{i}/{len(image_urls)}] 下载:{url[:60]}...')ifdownload_image(url,save_dir,headers):success_count+=1else:fail_count+=1# 下载间隔time.sleep(random.uniform(0.5,1.5))print(f'\n下载完成: 成功{success_count}张,失败{fail_count}张')# 使用示例:先爬取图片URL列表,再批量下载defget_image_urls_from_page(page_url):"""从页面中提取图片URL"""headers={'User-Agent':'Mozilla/5.0 ...'}response=requests.get(page_url,headers=headers)soup=BeautifulSoup(response.text,'lxml')image_urls=[]forimginsoup.select('div.gallery img'):src=img.get('src')orimg.get('data-src','')ifsrcandsrc.startswith('http'):image_urls.append(src)returnimage_urls# 主流程# page_url = 'https://example.com/gallery'# urls = get_image_urls_from_page(page_url)# batch_download_images(urls, save_dir='downloaded_images')

多线程加速下载

当图片数量多时,单线程速度太慢。可以用多线程并发下载。

fromconcurrent.futuresimportThreadPoolExecutor,as_completeddefbatch_download_with_threads(image_urls,save_dir='images',max_workers=5):"""多线程批量下载"""Path(save_dir).mkdir(parents=True,exist_ok=True)headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'}defdownload_task(args):idx,url=argsreturndownload_image(url,save_dir,headers)tasks=list(enumerate(image_urls,1))success=0withThreadPoolExecutor(max_workers=max_workers)asexecutor:future_to_url={executor.submit(download_task,task):taskfortaskintasks}forfutureinas_completed(future_to_url):idx,url=future_to_url[future]try:iffuture.result():success+=1exceptExceptionase:print(f'任务异常:{e}')print(f'多线程下载完成:{success}/{len(image_urls)}')

3 实战三:爬取表格数据并存入Excel

很多网站有表格形式的数据,比如排行榜、统计数据等。这个案例演示如何完整爬取这类数据。

安装依赖

pipinstallopenpyxl pandas

爬取天气历史数据

importrequestsfrombs4importBeautifulSoupimportpandasaspdfromdatetimeimportdatetimedefcrawl_table_data(url,table_selector='table'):""" 通用表格数据爬取函数 """headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'}response=requests.get(url,headers=headers,timeout=10)response.encoding='utf-8'soup=BeautifulSoup(response.text,'lxml')table=soup.select_one(table_selector)ifnottable:print(f'未找到表格:{table_selector}')returnNone# 提取表头headers_row=table.select('tr:first-child th')ifnotheaders_row:headers_row=table.select('thead tr th')columns=[th.text.strip()forthinheaders_row]# 提取数据行rows=[]fortrintable.select('tbody tr'):cells=tr.select('td')ifcells:row_data=[cell.text.strip()forcellincells]rows.append(row_data)ifnotcolumnsornotrows:print('表格数据为空')returnNone# 转换为DataFramedf=pd.DataFrame(rows,columns=columns)returndfdefsave_to_excel(df,filename='table_data.xlsx',sheet_name='数据'):"""保存到Excel,支持格式美化"""withpd.ExcelWriter(filename,engine='openpyxl')aswriter:df.to_excel(writer,sheet_name=sheet_name,index=False)# 获取worksheet对象进行格式调整ws=writer.sheets[sheet_name]# 自动调整列宽forcolumninws.columns:max_length=0col_letter=column[0].column_letterforcellincolumn:ifcell.value:max_length=max(max_length,len(str(cell.value)))ws.column_dimensions[col_letter].width=min(max_length+4,30)print(f'已保存到{filename}')# 多页表格数据爬取defcrawl_multi_page_table(base_url,total_pages,page_param='page'):"""多页表格数据爬取"""all_data=[]forpageinrange(1,total_pages+1):url=f'{base_url}?{page_param}={page}'print(f'爬取第{page}页...')df=crawl_table_data(url)ifdfisnotNone:df['来源页码']=page all_data.append(df)importtime time.sleep(1)ifall_data:result=pd.concat(all_data,ignore_index=True)print(f'共爬取{len(result)}条数据')returnresultreturnNone

4 完整项目:知乎热榜数据采集

importrequestsimportjsonimportcsvfromdatetimeimportdatetimedefcrawl_zhihu_hot():""" 爬取知乎热榜(接口版本,比解析HTML更稳定) """# 知乎热榜接口api_url='https://www.zhihu.com/api/v3/feed/topstory/hot-lists/total'headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36','Referer':'https://www.zhihu.com/hot','Accept':'application/json'}params={'limit':50,'desktop':'true'}response=requests.get(api_url,headers=headers,params=params,timeout=10)ifresponse.status_code!=200:print(f'请求失败:{response.status_code}')return[]data=response.json()hot_list=data.get('data',[])results=[]forrank,iteminenumerate(hot_list,1):target=item.get('target',{})results.append({'排名':rank,'标题':target.get('title',''),'热度':item.get('detail_text',''),'回答数':target.get('answer_count',0),'关注数':target.get('follower_count',0),'链接':f"https://www.zhihu.com/question/{target.get('id','')}",'采集时间':datetime.now().strftime('%Y-%m-%d %H:%M')})returnresultsdefsave_hot_list(data,filename=None):ifnotfilename:filename=f'zhihu_hot_{datetime.now().strftime("%Y%m%d_%H%M")}.csv'withopen(filename,'w',encoding='utf-8-sig',newline='')asf:writer=csv.DictWriter(f,fieldnames=data[0].keys())writer.writeheader()writer.writerows(data)print(f'已保存{len(data)}条热榜数据至{filename}')if__name__=='__main__':hot_data=crawl_zhihu_hot()ifhot_data:save_hot_list(hot_data)print(f'\n当前热榜前10:')foriteminhot_data[:10]:print(f"[{item['排名']}]{item['标题']}-{item['热度']}")

以上三个案例覆盖了静态爬虫的核心场景。注意在实际使用时,需要添加适当的请求延时,遵守网站robots.txt规则,不要爬取隐私数据。下一章进入爬虫的进阶领域:动态网页爬取。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/23 3:21:30

一键清零程序编写与开发

方案一:Windows 批处理脚本 (.bat)这个脚本会清理指定目录下的所有文件和子文件夹,只保留目录本身。脚本代码:batchecho off chcp 65001 >nul setlocal enabledelayedexpansion:: 请务必修改这个路径! set "TARGET_DIRC…

作者头像 李华
网站建设 2026/7/23 3:20:57

鸿蒙Flutter JSON解析与序列化:json_serializable代码生成详解

概述 json_serializable 是Flutter生态中最流行的JSON序列化代码生成工具,它可以自动生成 toJson() 和 fromJson() 方法,大大减少手动编写序列化代码的工作量。本文将详细介绍 json_serializable 的配置、使用方法和高级特性,帮助开发者实现自…

作者头像 李华
网站建设 2026/7/23 3:20:25

TM4C123BH6ZRB PWM故障保护与QEI编码器接口实战配置详解

1. 项目概述与核心价值在电机控制、工业自动化或者机器人关节驱动这类嵌入式应用里,我们工程师最头疼的两件事是什么?一是“输出要准”,二是“安全要稳”。输出不准,电机要么转不动,要么乱转;安全不稳&…

作者头像 李华
网站建设 2026/7/23 3:18:38

LangGraph入门

LangGraph入门很简陋的入门状态,第一部分LangGraph 本质上是一个低层的 Agent 编排与运行框架,重点不是“帮你写 Prompt”,而是管理状态、流程、持久化、流式输出和人工介入 模型 → 工具 → 模型 → 工具 → 模型 → END,实际上是一个循环1.…

作者头像 李华
网站建设 2026/7/23 3:15:56

RabbitMQ核心原理与应用实践:从消息中间件到分布式系统解耦

1. RabbitMQ 核心定位与核心价值RabbitMQ 是一款成熟稳定的开源消息代理和流处理中间件,采用 Erlang 语言开发,遵循 Mozilla Public License 2.0 开源协议。作为分布式系统中消息通信的基础设施,它通过高效的消息路由机制实现了生产者和消费者…

作者头像 李华
网站建设 2026/7/23 3:14:13

FastAPI连接MySQL实现自动建表

1. 启动本地MySQL服务Shell 终端输入:net start mysql80 ,先启动MySQL服务Shell 终端输入:mysql -u root -p ,然后输入密码,进入MySQL数据库Shell 终端输入:net stop mysql80 ,关闭MySQL服务She…

作者头像 李华