《数据采集与分析技术》课件-Python爬虫教学_第1页
《数据采集与分析技术》课件-Python爬虫教学_第2页
《数据采集与分析技术》课件-Python爬虫教学_第3页
《数据采集与分析技术》课件-Python爬虫教学_第4页
《数据采集与分析技术》课件-Python爬虫教学_第5页
已阅读5页,还剩95页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第1份/5Python爬虫教学01请求与网页结构把浏览器行为翻译成requests代码01请求入门02解析清洗03多页会话04稳定合规05项目实战先理解HTTP,爬虫才不是复制粘贴代码。能请求一个公开静态网页,读懂状态码、响应头、编码与网页结构。本节会完成建立请求-响应心智模型写出fetch_page请求函数完成静态页面到CSV的最小闭环课堂代码预览importrequestsresp=requests.get(url,timeout=10)print(resp.status_code)print(resp.text[:120])Python爬虫功能教学|01/05请求与网页结构01/20COURSEMAP本份课件完成从浏览器到最小爬虫脚本的入门闭环。本页说明本份课件在五份课程中的位置,以及本份内部的学习顺序。01边界与目标本节内部模块02HTTP基础本节内部模块03requests请求本节内部模块04HTML结构本节内部模块05保存与练习本节内部模块01请求入门02解析清洗03多页会话04稳定合规05项目实战Python爬虫功能教学|01/05请求与网页结构02/20BOUNDARY爬虫课程从公开页面和合规边界开始。技术之前先确定什么能抓、抓到什么程度、如何降低对网站的影响。教学要点只面向公开、允许访问的练习页面不登录、不绕过验证码、不采集私有数据设置timeout、限速和页数上限保留来源说明,便于课堂复盘课堂边界先小规模验证遇到拒绝先停止不要把练习站当压测对象Python爬虫功能教学|01/05请求与网页结构03/20REQUESTMODEL浏览器打开网页,本质上也是一次请求和响应。把浏览器动作拆成可观察步骤,后续才知道requests在模拟哪一段。1输入URL确定资源地址2发送请求GET/POST3服务器响应状态码与正文4浏览器渲染HTML/CSS/JS5人工阅读看到页面内容转成代码Python只负责请求和处理响应渲染后的动态内容另行判断先从静态HTML学起Python爬虫功能教学|01/05请求与网页结构04/20URLANATOMYURL的组成决定分页、参数和相对链接怎么处理。课程中先学会拆URL,再写urljoin、分页参数和去重规则。组成例子教学用途schemehttps确认协议host确定站点path/items/42定位资源query?page=2识别分页参数fragment#section通常不参与请求记忆点query常用于分页path常用于详情页fragment不会发给服务器Python爬虫功能教学|01/05请求与网页结构05/20HTTPSIGNALS状态码和响应头决定代码下一步怎么走。先检查响应对象,再进入解析;不要拿到text就直接select。信号含义处理200成功继续解析301/302跳转确认最终URL403/429受限或过快停止检查规则5xx服务端异常稍后有限重试Content-Type内容类型区分HTML/JSON检查顺序status_codeheadersencodingtext预览Python爬虫功能教学|01/05请求与网页结构06/20ENCODING编码问题要在解析前处理,否则字段会从源头变脏。中文乱码常见于响应头缺失或声明不准确,先修正响应编码再交给解析器。教学要点优先查看Content-Type中的charsetrequests可以使用apparent_encoding推断保存文件时统一指定utf-8-sig或utf-8不要在解析后再到处手动替换乱码排查顺序headersapparent_encodingtext预览Python爬虫功能教学|01/05请求与网页结构07/20DEVTOOLS开发者工具能帮你确认看到的是源码还是渲染结果。静态页面可以直接从HTML解析;动态页面需要后续课程判断接口或浏览器自动化。教学要点Elements面板看DOM结构Network面板看真实请求Response里确认HTML/JSONPreview适合快速理解字段层级课堂操作打开Network后刷新页面点开第一条document请求复制公开页面URL做练习Python爬虫功能教学|01/05请求与网页结构08/20REQUESTSSETUPrequests是入门阶段最小可用的HTTP客户端。先用同步请求掌握概念;并发、框架和浏览器自动化放到后续阶段。安装与第一次请求python-mvenv.venv.venv\Scripts\activatepipinstallrequestsbeautifulsoup4importrequestsresp=requests.get("",timeout=10)print(resp.status_code)print(resp.headers.get("Content-Type"))函数拆解1venv隔离课堂依赖2timeout避免无限等待3headers先观察再设置Python爬虫功能教学|01/05请求与网页结构09/20FETCHFUNCTIONfetch_page把请求细节封装成稳定入口。每个爬虫都应该有统一的请求函数,便于后面加入日志、重试和限速。请求函数importrequestsHEADERS={"User-Agent":"python-course-bot/1.0"}deffetch_page(url:str)->str:resp=requests.get(url,headers=HEADERS,timeout=10)resp.raise_for_status()resp.encoding=resp.apparent_encodingreturnresp.text函数拆解1HEADERS说明客户端身份2raise_for_status错误尽早暴露3encoding减少中文乱码Python爬虫功能教学|01/05请求与网页结构10/20RESPONSECHECK响应对象先检查,再解析。入门阶段要求每次请求都打印关键字段,形成可观察习惯。教学要点status_code是否为200url是否发生跳转Content-Type是否符合预期text前200字符是否像HTML常见误判返回登录页也可能是200乱码不一定是解析问题空字符串先查响应Python爬虫功能教学|01/05请求与网页结构11/20EXCEPTION请求异常要被记录,而不是让程序静默失败。入门版先用try/except包住单次请求,后续再扩展重试与日志。异常处理骨架importrequeststry:html=fetch_page(url)exceptrequests.Timeout:print("timeout",url)exceptrequests.HTTPErrorasexc:print("httperror",exc.response.status_code)exceptrequests.RequestExceptionasexc:print("requestfailed",exc)函数拆解1Timeout网络等待超时2HTTPError状态码异常3RequestException请求总异常基类Python爬虫功能教学|01/05请求与网页结构12/20DOMMODELHTML要按DOM树理解,而不是当成一整段字符串。先找重复容器,再从容器里找字段,能避免标题和链接错配。html模块/字段/状态body模块/字段/状态div.item-card模块/字段/状态a.title模块/字段/状态span.price模块/字段/状态p.desc模块/字段/状态定位口诀先容器再字段后清洗Python爬虫功能教学|01/05请求与网页结构13/20BEAUTIFULSOUPBeautifulSoup让HTML解析变成选择节点。入门只需掌握select、select_one、get_text和属性读取。解析第一组字段frombs4importBeautifulSoupsoup=BeautifulSoup(html,"html.parser")card=soup.select_one(".item-card")title=card.select_one("a.title").get_text(strip=True)href=card.select_one("a.title")["href"]price=card.select_one(".price").get_text(strip=True)print(title,href,price)函数拆解1select_one取第一个匹配节点2get_text提取文本3attrs读取href等属性Python爬虫功能教学|01/05请求与网页结构14/20SELECTORFIRST第一个选择器只解决一个字段,不要一次写全。课堂调试顺序是:容器数量、标题字段、链接字段、其他字段。教学要点先确认soup.select返回条数select_one为空时先打印容器HTML不要用过深层级绑定页面装饰字段名称与输出字典保持一致调试动作print(len(cards))print(card.prettify()[:500])逐字段验证Python爬虫功能教学|01/05请求与网页结构15/20SAVECSV保存文件让爬虫结果可检查、可提交。入门阶段CSV最容易查看,注意字段名、编码和换行。CSV保存importcsvdefsave_csv(rows,path):withopen(path,"w",newline="",encoding="utf-8-sig")asf:writer=csv.DictWriter(f,fieldnames=["title","url","price"])writer.writeheader()writer.writerows(rows)函数拆解1utf-8-sig方便Excel打开中文2fieldnames稳定字段顺序3newline避免空行Python爬虫功能教学|01/05请求与网页结构16/20MINICASE最小案例只抓一页,但必须跑完整链路。课堂目标是把请求、解析、清洗、保存串起来,而不是追求数量。1请求页面fetch_page2定位容器.item-card3提取字段title/url4保存CSVrows5复查结果打开文件验收能重复运行字段不为空文件能打开Python爬虫功能教学|01/05请求与网页结构17/20COMMONERRORS入门阶段最常见错误来自过快进入解析。先观察响应,再定位结构;每一步都输出少量诊断信息。教学要点没有timeout导致卡住把动态渲染内容当静态HTML相对链接没有补全编码错误导致中文乱码异常被except后直接pass修复顺序先响应再选择器后保存Python爬虫功能教学|01/05请求与网页结构18/20CLASSLAB完成一个公开静态页面采集,才进入下一份解析课。练习限制在一页,重点是结构清晰、结果可检查。课堂任务抓取公开练习页面中的title、url、price三个字段,并保存为CSV。建议30-45分钟,要求小规模、可复跑、可解释。完成标准fetch_page有timeout和状态码检查至少提取10条记录CSV字段名清晰且链接为绝对地址思考题如果status_code是403,应该继续尝试还是停止?为什么不要直接用正则解析整页HTML?01请求入门02解析清洗03多页会话04稳定合规05项目实战Python爬虫功能教学|01/05请求与网页结构19/20RECAP本份课件建立了从URL到CSV的最小闭环。下一份将把重点从请求转向解析质量,让一页数据提取得更准。本份掌握HTTP请求-响应模型requests请求函数DOM和BeautifulSoup入门CSV保存和课堂练习下一步下一份:解析提取与清洗01请求入门02解析清洗03多页会话04稳定合规05项目实战Python爬虫功能教学|01/05请求与网页结构20/20第2份/5Python爬虫教学02解析提取与清洗从网页结构中稳定提取字段01请求入门02解析清洗03多页会话04稳定合规05项目实战第二步不是抓更多页面,而是把一页解析准。掌握CSS、XPath、字段清洗、空值保护和解析测试。本节会完成从重复容器开始提取选择稳定选择器把HTML转成干净字典课堂代码预览soup=BeautifulSoup(html,"html.parser")forcardinsoup.select(".item-card"):title=card.select_one("a.title")price=card.select_one(".price")Python爬虫功能教学|02/05解析提取与清洗01/20COURSEMAP本份课件把一页HTML解析成稳定、可测试的数据结构。本页说明本份课件在五份课程中的位置,以及本份内部的学习顺序。01容器优先本节内部模块02CSS/XPath本节内部模块03字段清洗本节内部模块04JSON与正则本节内部模块05测试与质量门本节内部模块01请求入门02解析清洗03多页会话04稳定合规05项目实战Python爬虫功能教学|02/05解析提取与清洗02/20PIPELINE解析流程从页面块开始,而不是从单个字段开始。先锁定重复容器,可以避免字段串行查找造成错配。1容器.item-card2字段title/price3清洗strip/replace4补全urljoin5校验必填字段输出形态list[dict]字段名稳定缺失值可见Python爬虫功能教学|02/05解析提取与清洗03/20CONTAINER重复容器是解析稳定性的第一锚点。先确认每条数据的外层容器,再在容器内部查字段。教学要点容器数量应接近页面显示数量字段查询只在当前容器内进行容器选择器不要过深容器为空时先回到HTML样本检查调试顺序len(cards)card.prettify()逐字段select_onePython爬虫功能教学|02/05解析提取与清洗04/20CSSBASICSCSS选择器适合快速定位类名、标签和属性。BeautifulSoup入门阶段优先使用CSSSelector,语法短、可读性好。语法含义例子.itemclass选择soup.select('.item')a.title标签+classcard.select_one('a.title')div>a直接子元素card.select('div>a')[href]属性存在card.select('a[href]')a[href^='/']属性前缀相对链接优点短直观适合课堂演示Python爬虫功能教学|02/05解析提取与清洗05/20CSSCOMBO组合选择器要表达结构,不要复制整条浏览器路径。过深的选择器通常脆弱,页面小改版就会失效。写法用途风险.card.title容器内字段推荐ul.items>li直接列表项可用body>div>div绝对层级脆弱:nth-child(3)位置定位易改版[data-id]业务属性较稳定课堂原则短选择器业务语义先容器后字段Python爬虫功能教学|02/05解析提取与清洗06/20XPATHBASICSXPath适合处理文本、位置和兄弟节点关系。当页面没有稳定class时,XPath可以表达更细的结构关系。语法含义例子//div任意层级div//div[@class='item']./a当前节点下aitem.xpath('./a')@href取属性./a/@hreftext()取文本./h2/text()contains()包含判断contains(@class,'item')使用场景lxmlScrapy复杂关系Python爬虫功能教学|02/05解析提取与清洗07/20XPATHAXES轴关系能解决字段在兄弟节点附近的问题。不要一开始就用复杂XPath;只有CSS表达困难时再切换。教学要点following-sibling找后面的兄弟节点parent回到父节点contains(text(),...)按文本定位normalize-space清理节点文本注意表达越复杂越要写注释避免纯位置依赖先在样本上测试Python爬虫功能教学|02/05解析提取与清洗08/20CHOICECSS、XPath、正则和JSONpath要按数据来源选择。选择工具的标准是稳定、可读、可测试,而不是复杂。方法适合场景边界CSS类名和结构清晰不擅长文本关系XPath位置和文本关系语法更复杂正则字段二次清洗不要解析整页HTMLJSONpath接口返回JSON先确认来源合规手写split极简单文本维护性差判断数据在哪结构多稳测试难不难Python爬虫功能教学|02/05解析提取与清洗09/20PARSERDESIGNparse_items只负责解析,不负责请求。职责分离后,解析函数可以用本地HTML样本反复测试。解析函数骨架frombs4importBeautifulSoupdefparse_items(html:str)->list[dict]:soup=BeautifulSoup(html,"html.parser")rows=[]forcardinsoup.select(".item-card"):rows.append(parse_card(card))returnrows函数拆解1parse_items处理整页2parse_card处理单条记录3rows统一输出list[dict]Python爬虫功能教学|02/05解析提取与清洗10/20NONESAFE字段缺失要返回None,而不是让程序崩溃。真实页面常有缺字段、广告卡片和空标签,解析函数必须显式处理。空值保护deftext_or_none(node):returnnode.get_text(strip=True)ifnodeelseNonedefattr_or_none(node,name):returnnode.get(name)ifnodeandnode.has_attr(name)elseNonetitle_node=card.select_one("a.title")title=text_or_none(title_node)href=attr_or_none(title_node,"href")函数拆解1select_one可能返回None2has_attr属性可能不存在3None让缺失可见Python爬虫功能教学|02/05解析提取与清洗11/20TEXTCLEAN清洗文本要在入库前完成,规则要集中。脏数据越早进入文件,后面越难排查来源。教学要点strip去掉首尾空白replace处理换行和特殊空格价格字段拆出数值和单位日期字段统一格式保留原始字段便于复查清洗原则可解释可重复不要过度猜测Python爬虫功能教学|02/05解析提取与清洗12/20URLJOIN相对链接必须补全为绝对地址。保存相对链接会让后续详情页抓取、去重和复查都变困难。链接补全fromurllib.parseimporturljoindefclean_link(base_url,href):ifnothref:returnNonereturnurljoin(base_url,href)row={"url":clean_link(base_url,href)}函数拆解1base_url当前页面URL2href节点属性3urljoin兼容相对路径Python爬虫功能教学|02/05解析提取与清洗13/20REGEXROLE正则适合清洗字段,不适合解析整页HTML。先用HTML解析器定位字段,再用正则从字段文本里提取数字或日期。教学要点从价格文本提取数字从标题中提取编号标准化日期格式校验字段是否符合预期边界不要跨标签匹配不要替代DOM解析写清楚模式含义Python爬虫功能教学|02/05解析提取与清洗14/20JSONDATA如果响应是JSON,直接按结构取字段。接口数据通常比HTML更结构化,但必须确认数据来源公开且允许访问。JSON解析importrequestsresp=requests.get(api_url,timeout=10)resp.raise_for_status()data=resp.json()rows=[]foritemindata.get("items",[]):rows.append({"title":item.get("title"),"url":item.get("url")})函数拆解1resp.json直接解析JSON2get避免KeyError3来源只处理允许访问的数据Python爬虫功能教学|02/05解析提取与清洗15/20PARSERTEST解析函数要有本地样本测试,避免每次都请求网站。把sample.html保存下来,解析测试可以离线运行。解析测试deftest_parse_items():html=Path("sample.html").read_text(encoding="utf-8")rows=parse_items(html)assertlen(rows)>=3assertrows[0]["title"]assertrows[0]["url"].startswith("https://")函数拆解1sample.html固定样本2assert验证核心字段3离线减少无意义请求Python爬虫功能教学|02/05解析提取与清洗16/20QUALITYGATE质量门能及时发现页面改版和选择器失效。解析结果为空时不应静默保存空文件,而应记录并提醒检查。检查项阈值动作记录数>0否则报警必填字段title/url缺失记录错误重复率低于上限检查去重字段格式符合规则记录异常样本预览前3条人工复查收益早发现可解释便于重跑Python爬虫功能教学|02/05解析提取与清洗17/20ANTIPATTERN脆弱选择器会让爬虫看起来能跑、实际不可靠。如果选择器只在当前浏览器复制路径里成立,应主动简化。教学要点直接复制Copyselector的超长路径依赖随机class或样式class用nth-child定位业务字段多个字段从全页查找导致错配缺失值被空字符串吞掉修复找业务容器缩短选择器写解析测试Python爬虫功能教学|02/05解析提取与清洗18/20CLASSLAB解析练习要交付字段准确、异常可见的结果。给定商品列表HTML,提取四个字段并写解析测试。课堂任务提取title、url、price、rating,保存为list[dict]并通过3个断言。建议30-45分钟,要求小规模、可复跑、可解释。完成标准parse_items不发网络请求缺字段时不崩溃链接补全为绝对地址思考题选择器失效时,最先检查哪一步?为什么解析测试比反复请求网站更适合课堂?01请求入门02解析清洗03多页会话04稳定合规05项目实战Python爬虫功能教学|02/05解析提取与清洗19/20RECAP本份课件把一页HTML变成可测试的数据结构。下一份会把单页能力扩展到分页、详情页、队列和会话状态。本份掌握容器优先CSS/XPath选择字段清洗与补全解析测试和质量门下一步下一份:分页详情与会话01请求入门02解析清洗03多页会话04稳定合规05项目实战Python爬虫功能教学|02/05解析提取与清洗20/20第3份/5Python爬虫教学03分页详情与会话从单页采集扩展到多页任务01请求入门02解析清洗03多页会话04稳定合规05项目实战第三步开始处理页面关系:列表、分页、详情页。掌握分页规则、URL队列、去重、Session和失败恢复。本节会完成识别分页模式构建列表到详情的抓取图用队列和seen控制多页访问课堂代码预览queue=deque([(start_url,"list")])seen=set()whilequeue:url,page_type=queue.popleft()Python爬虫功能教学|03/05分页详情与会话01/20COURSEMAP本份课件把单页解析扩展为可控的多页采集流程。本页说明本份课件在五份课程中的位置,以及本份内部的学习顺序。01分页规则本节内部模块02列表-详情本节内部模块03队列去重本节内部模块04Session本节内部模块05断点与调试本节内部模块01请求入门02解析清洗03多页会话04稳定合规05项目实战Python爬虫功能教学|03/05分页详情与会话02/20FROMONEPAGE多页爬虫不是把页码循环写大。扩展前先确认分页规则、停止条件和页面类型。教学要点确认下一页如何产生限制课堂页数上限列表页和详情页分开解析每次运行记录抓取页数和记录数风险无限翻页重复抓取详情页失败丢数据Python爬虫功能教学|03/05分页详情与会话03/20PAGINATIONTYPES分页模式决定URL生成方式。不同分页模式不要混用同一段循环代码。模式信号处理query参数?page=2构造下一页URL下一页链接a.next解析next_urloffset/limitoffset=20按步长递增接口分页JSONhas_more读响应字段无限滚动Network请求只处理公开允许接口停止条件无next空列表达到上限Python爬虫功能教学|03/05分页详情与会话04/20NEXTLINK优先从页面解析下一页链接,而不是猜页数。页面给出的next链接通常比手写page+1更稳。1解析列表items2找nexta.next3urljoin绝对地址4入队queue5停止next为空优势跟随站点规则减少越界便于调试Python爬虫功能教学|03/05分页详情与会话05/20QUERYPAGEquery参数分页要集中生成URL。不要把字符串拼接散落在循环里;统一函数更容易测试。页码URLfromurllib.parseimporturlencode,urlsplit,urlunsplit,parse_qsdefwith_page(url,page):parts=urlsplit(url)query=parse_qs(parts.query)query["page"]=[str(page)]new_query=urlencode(query,doseq=True)returnurlunsplit(parts._replace(query=new_query))函数拆解1urlsplit拆URL2parse_qs保留原参数3doseq正确编码列表值Python爬虫功能教学|03/05分页详情与会话06/20LISTDETAIL列表页负责发现链接,详情页负责补全字段。页面类型拆开后,解析函数职责更清楚,失败也更容易重跑。start_url模块/字段/状态listpage1模块/字段/状态listpage2模块/字段/状态detailurl模块/字段/状态detailparser模块/字段/状态storage模块/字段/状态拆分收益减少重复代码便于失败重跑字段来源清晰Python爬虫功能教学|03/05分页详情与会话07/20QUEUE队列加去重集合,是多页爬虫的最小调度器。课堂版先保证顺序清晰、状态可观察,不追求并发。URL队列fromcollectionsimportdequequeue=deque([(start_url,"list")])seen=set()whilequeue:url,kind=queue.popleft()ifurlinseen:continueseen.add(url)html=fetch_page(url)函数拆解1queue待访问URL2seen避免重复3kind区分页面类型Python爬虫功能教学|03/05分页详情与会话08/20LISTPARSER列表解析函数输出记录和下一页。函数返回两个对象:当前页的详情链接,以及下一页URL。parse_listdefparse_list(html,base_url):soup=BeautifulSoup(html,"html.parser")items=[]forcardinsoup.select(".item-card"):href=card.select_one("a.title")["href"]items.append({"url":urljoin(base_url,href)})next_node=soup.select_one("a.next")next_url=urljoin(base_url,next_node["href"])ifnext_nodeelseNonereturnitems,next_url函数拆解1items详情页入口2next_url分页入口3base_url补全链接Python爬虫功能教学|03/05分页详情与会话09/20DETAILPARSER详情页解析补充长文本和附加字段。列表页不要承担所有字段;详情页字段单独维护。parse_detaildefparse_detail(html,url):soup=BeautifulSoup(html,"html.parser")return{"url":url,"title":text_or_none(soup.select_one("h1")),"description":text_or_none(soup.select_one(".desc")),"date":text_or_none(soup.select_one("time")),}函数拆解1url保留来源2h1详情标题3desc详情字段Python爬虫功能教学|03/05分页详情与会话10/20SESSIONSession复用连接和上下文,但不等于突破权限。只对允许访问的公开内容使用Session,不采集登录后私有数据。教学要点统一headers和timeout复用TCP连接提升稳定性保留公开页面需要的上下文不用于绕过登录、验证码或访问控制合规提醒不处理验证码绕过不抓私有数据遇到拒绝先停止Python爬虫功能教学|03/05分页详情与会话11/20SESSIONCODESession应该被封装在fetcher内部。调用方只关心fetch_page,连接复用细节不向外扩散。Sessionfetcherimportrequestssession=requests.Session()session.headers.update({"User-Agent":"python-course-bot/1.0"})deffetch_page(url):resp=session.get(url,timeout=10)resp.raise_for_status()returnresp.text函数拆解1Session复用连接2headers统一设置3fetch_page对外接口Python爬虫功能教学|03/05分页详情与会话12/20RATELIMIT多页采集必须限制速度和规模。页数变多后,最容易出现请求过快、重复抓取和难以停止的问题。教学要点每次请求之间sleep课堂设置max_pages记录已访问URL数量遇到429或403停止检查默认值delay:1smax_pages:3-5max_attempts:3Python爬虫功能教学|03/05分页详情与会话13/20CHECKPOINT断点文件让失败后可以恢复进度。入门版可以把seen和结果持续写到文件,避免失败后全部重来。简单断点defsave_seen(seen,path):Path(path).write_text("\n".join(sorted(seen)),encoding="utf-8")defload_seen(path):p=Path(path)ifnotp.exists():returnset()returnset(p.read_text(encoding="utf-8").splitlines())函数拆解1seen访问历史2path本地状态3恢复失败后继续Python爬虫功能教学|03/05分页详情与会话14/20URLNORMALIZEURL规范化能减少重复访问。同一页面可能有不同写法,入队前要做基本整理。教学要点去掉无意义fragment补全相对链接统一尾部斜杠策略排序或保留必要query参数保存canonicalURL便于去重注意不要删除业务参数先保守处理记录原始URLPython爬虫功能教学|03/05分页详情与会话15/20DUPLICATE去重分为URL去重和记录去重。URL不重复不代表数据不重复,存储前还要检查业务键。层级键位置URL去重normalized_url入队前详情记录item_id/url保存前文件追加hash(row)写入前数据库uniqueindex表结构日志request_id排错课堂要求至少URL去重保存记录数重复要可见Python爬虫功能教学|03/05分页详情与会话16/20DYNAMICPAGE无限滚动要先判断数据是否来自公开接口。本课程只讲观察公开请求和合规使用,不讲绕过登录、签名或验证码。教学要点Network查看滚动时新增请求确认返回HTML还是JSON确认接口无需登录且允许访问设置页数、频率和字段范围边界不绕过签名不破解验证码不抓私有接口Python爬虫功能教学|03/05分页详情与会话17/20DEBUG分页调试看页码、URL、条数和停止原因。每页输出少量摘要,比打印整页HTML更有效。教学要点page_indexcurrent_urlitem_countnext_urlqueue_sizestop_reason日志样例page=2items=20next=Nonestopdetail_failed=1Python爬虫功能教学|03/05分页详情与会话18/20CLASSLAB完成列表到详情页的闭环,才算进入真实爬虫任务。练习限制前3页,重点是URL发现、去重和字段合并。课堂任务从公开练习站点前3页进入详情页,保存title、url、detail_text。建议30-45分钟,要求小规模、可复跑、可解释。完成标准列表页和详情页解析函数分开seen_urls避免重复抓取日志输出每页抓取数和详情数思考题分页停止条件应该写在哪里?详情页失败时,是否保留列表页字段?01请求入门02解析清洗03多页会话04稳定合规05项目实战Python爬虫功能教学|03/05分页详情与会话19/20RECAP本份课件把单页脚本扩展为可控的多页采集流程。下一份将处理稳定性、限速、错误日志和合规边界。本份掌握分页模式列表-详情图队列与seenSession与断点下一步下一份:稳定性与合规01请求入门02解析清洗03多页会话04稳定合规05项目实战Python爬虫功能教学|03/05分页详情与会话20/20第4份/5Python爬虫教学04稳定性与合规让爬虫可控、可恢复、不过界01请求入门02解析清洗03多页会话04稳定合规05项目实战第四步处理现实问题:失败、限速、日志和边界。让爬虫能在公开允许范围内稳定运行,并且失败可见、可恢复。本节会完成设置限速和有限重试记录错误与进度遵守robots.txt、服务条款和数据权限课堂代码预览forurlinurls:try:html=fetch_page(url)exceptExceptionasexc:log_error(url,exc)time.sleep(1.0)Python爬虫功能教学|04/05稳定性与合规01/20COURSEMAP本份课件把能跑的脚本变成可控、合规、可诊断的程序。本页说明本份课件在五份课程中的位置,以及本份内部的学习顺序。01合规边界本节内部模块02限速重试本节内部模块03日志进度本节内部模块04质量监控本节内部模块05停止条件本节内部模块01请求入门02解析清洗03多页会话04稳定合规05项目实战Python爬虫功能教学|04/05稳定性与合规02/20MINDSET稳定性不是为了抓更多,而是为了不失控。多页任务失败很正常,关键是知道失败在哪里、是否应该继续。教学要点每个请求有timeout每类错误有处理策略每次运行有日志每个任务有停止条件课堂目标可观察可恢复不过界Python爬虫功能教学|04/05稳定性与合规03/20POLITE合规爬取先定义边界,再写代码。本课程不讲绕过登录、验证码、封禁或访问控制;稳定性只用于公开允许的数据采集。1确认公开页面2遵守robots/ToS3克制限速上限4标识合理UA5停止被拒绝排查不做事项不绕过验证码不采集私有内容不高频请求Python爬虫功能教学|04/05稳定性与合规04/20ROBOTSrobots.txt和服务条款是边界检查的一部分。课堂中不把robots当作绕过对象,而是作为是否继续的判断依据。教学要点查看站点是否声明抓取规则尊重禁止路径和频率要求不采集个人隐私和敏感数据在README中说明数据来源处理方式禁止就停止不确定就缩小范围保留来源说明Python爬虫功能教学|04/05稳定性与合规05/20ERRORTYPES把失败分类,处理策略才不会混乱。不是所有错误都应该重试;访问受限通常应该停止。类型信号处理网络超时Timeout退避后有限重试服务异常500/502/503稍后重试请求过快429降频或停止访问受限403/登录页停止检查边界页面改版字段为空告警更新选择器原则临时故障才重试权限问题不绕过异常要记录Python爬虫功能教学|04/05稳定性与合规06/20BACKOFF重试要有次数和退避,不能无限循环。有限重试可以处理临时网络问题,但不能掩盖边界问题。有限重试RETRY_STATUS={500,502,503,504}deffetch_with_retry(url,max_attempts=3):forattemptinrange(1,max_attempts+1):resp=requests.get(url,timeout=10)ifresp.status_codenotinRETRY_STATUS:resp.raise_for_status()returnresp.texttime.sleep(2**(attempt-1))raiseRuntimeError(f"fetchfailed:{url}")函数拆解1max_attempts有限次数2RETRY_STATUS临时故障3backoff逐步退避Python爬虫功能教学|04/05稳定性与合规07/20STOPCONDITIONS停止条件比继续尝试更重要。爬虫应该知道什么时候结束,什么时候暂停,什么时候报警。教学要点无下一页或结果为空达到max_pages或max_items连续失败超过阈值出现403、登录页或验证码解析结果低于质量阈值输出stop_reasonlast_urlprocessed_countPython爬虫功能教学|04/05稳定性与合规08/20RATELIMIT限速要放在统一请求入口附近。不要让每个解析函数自己sleep;统一调度更可控。限速包装importtimedefcrawl_urls(urls,delay=1.0):forurlinurls:start=time.time()html=fetch_with_retry(url)yieldurl,htmlelapsed=time.time()-starttime.sleep(max(0,delay-elapsed))函数拆解1delay请求间隔2elapsed扣除请求耗时3yield流式处理Python爬虫功能教学|04/05稳定性与合规09/20LOGFIELDS日志让爬虫从黑盒脚本变成可诊断程序。至少记录URL、状态码、耗时、解析数量和异常原因。字段说明用途timestamp发生时间定位运行批次url请求地址复查失败页面status_code响应状态分类错误elapsed_ms请求耗时观察性能item_count解析条数发现改版格式CSVJSONL普通日志Python爬虫功能教学|04/05稳定性与合规10/20LOGGING使用logging替代散落的print。日志级别能区分进度、警告和错误,便于后续筛选。logging示例importlogginglogging.basicConfig(filename="crawler.log",level=logging.INFO,format="%(asctime)s%(levelname)s%(message)s",)("fetchedurl=%scount=%s",url,item_count)logging.exception("failedurl=%s",url)函数拆解1INFO正常进度2WARNING可恢复异常3ERROR需要处理Python爬虫功能教学|04/05稳定性与合规11/20ERRORCSV失败URL单独保存,便于后续重跑。不要只在屏幕上打印错误;程序结束后仍要能找到失败列表。错误记录importcsvdefappend_error(path,url,reason):exists=Path(path).exists()withopen(path,"a",newline="",encoding="utf-8-sig")asf:writer=csv.DictWriter(f,fieldnames=["url","reason"])ifnotexists:writer.writeheader()writer.writerow({"url":url,"reason":reason})函数拆解1append持续追加2reason错误原因3重跑只处理失败URLPython爬虫功能教学|04/05稳定性与合规12/20CHECKPOINT进度文件让爬虫失败后不用从头开始。小项目可以用本地文件保存seen_urls和已保存记录。教学要点每处理一页就保存状态结果文件追加写入启动时加载seen_urls记录当前页码或last_url注意状态文件要可读不要和数据混放重跑要先备份Python爬虫功能教学|04/05稳定性与合规13/20IDEMPOTENT重复运行不应该制造重复数据。可重复运行是教学项目可交付的基本要求。教学要点保存前按url或item_id去重数据库设置唯一键CSV追加前读入已有键日志记录skipped_duplicate目标可复跑可解释不重复Python爬虫功能教学|04/05稳定性与合规14/20DRIFT页面结构变化要被质量门发现。当item_count突然变为0,通常是选择器失效或页面改版。信号可能原因动作item_count=0容器选择器失效保存样本并报警字段缺失升高字段结构改变检查字段选择器状态码正常但内容异常返回登录页/提示页停止检查边界重复率异常分页重复检查next_url耗时异常网络或站点变慢降低频率质量门数量字段重复格式Python爬虫功能教学|04/05稳定性与合规15/20PRIVACY数据边界不仅是技术问题,也是教学责任。课程作业不采集个人敏感信息,不公开不必要的原始页面。教学要点不采集身份证、手机号等敏感字段不采集登录后内容不把个人数据上传到公开仓库报告中说明数据来源和用途课堂要求公开练习站最小字段结果只用于教学Python爬虫功能教学|04/05稳定性与合规16/20USERAGENTUser-Agent用来说明客户端身份,不是伪装工具。合理标识有助于负责地访问公开页面,但不能用于绕过限制。教学要点说明课程用途包含联系或项目标识时更清楚不要冒充真实浏览器绕过规则遇到拒绝时停止而不是继续变化UA示例python-course-bot/1.0contactinREADME遵守限速Python爬虫功能教学|04/05稳定性与合规17/20DONOTDO这门课的稳定性不包含绕过访问控制。把禁区写清楚,学生更容易形成正确边界。教学要点不破解验证码不绕过登录或付费墙不规避封禁策略不高频请求影响网站不采集和传播敏感个人数据处理方式停止缩小任务换公开练习源Python爬虫功能教学|04/05稳定性与合规18/20CLASSLAB稳定性练习的目标,是让失败可见且可恢复。给上一节多页爬虫加入限速、有限重试、错误日志和进度日志。课堂任务为多页爬虫增加delay、max_attempts、error.csv、crawler.log和stop_reason。建议30-45分钟,要求小规模、可复跑、可解释。完成标准每个请求间隔至少1秒临时错误最多重试3次失败URL单独保存,程序不中断思考题哪些状态码不应该重试?为什么日志里要记录item_count?01请求入门02解析清洗03多页会话04稳定合规05项目实战Python爬虫功能教学|04/05稳定性与合规19/20RECAP本份课件把爬虫从脚本推进到可控程序。下一份会把前四份能力整合成一个可交付项目。本份掌握合规边界限速与有限重试日志和错误文件质量门与停止条件下一步下一份:项目实战与维护01请求入门02解析清洗03多页会话04稳定合规05项目实战Python爬虫功能教学|04/05稳定性与合规20/20第5份/5Python爬虫教学05项目实战与维护把脚本整理成可维护项目01请求入门02解析清洗03多页会话04稳定合规05项目实战最后一步把功能拼成项目:配置、模块、存储、运行记录。完成一个合规公开数据采集项目,并能交给别人运行和维护。本节会完成拆分fetcher、parser、storage选择合适存储格式写README、运行参数和验收标准课堂代码预览crawler_project/config.pyfetcher.pyparser.pystorage.pymain.pyREADME.mdPython爬虫功能教学|05/05项目实战与维护01/20COURSEMAP本份课件把前四份能力整合成一个可交付项目。本页说明本份课件在五份课程中的位置,以及本份内部的学习顺序。01需求定义本节内部模块02模块拆分本节内部模块03存储测试本节内部模块04README本节内部模块05验收复盘本节内部模块01请求入门02解析清洗03多页会话04稳定合规05项目实战Python爬虫功能教学|05/05项目实战与维护02/20CAPSTONEREQ结课项目先写需求,而不是先写代码。需求越具体,越容易控制规模、边界和验收标准。教学要点数据来源必须公开允许字段范围最小且清晰限制页数和请求频率输出文件可复查README说明运行方式项目边界不登录不绕过小规模Python爬虫功能教学|05/05项目实战与维护03/20ARCHITECTURE项目化不是变复杂,而是让每个模块只承担一个职责。抓取、解析、保存、日志分开后,问题能定位到模块。config模块/字段/状态fetcher模块/字段/状态parser模块/字段/状态storage模块/字段/状态main模块/字段/状态logs模块/字段/状态项目收益可测试可复跑可交付Python爬虫功能教学|05/05项目实战与维护04/20FOLDER清晰目录结构能降低教学项目的维护成本。让学生打开项目就知道入口、配置、样本和输出在哪里。文件职责说明config.py配置URL、delay、输出路径fetcher.py请求timeout、重试、日志parser.py解析字段提取和清洗storage.py保存CSV/JSONL/SQLitemain.py入口组织流程补充tests/sample.htmlREADME.mdPython爬虫功能教学|05/05项目实战与维护05/20CONFIG配置文件集中管理可变参数。不要把URL、页数、延迟散落在多个函数里。config.pySTART_URL="/items"OUTPUT="data/items.csv"ERROR_FILE="logs/errors.csv"DELAY_SECONDS=1.0MAX_PAGES=3USER_AGENT="python-course-bot/1.0"函数拆解1集中方便修改2显式便于审查3默认值控制规模Python爬虫功能教学|05/05项目实战与维护06/20FETCHERfetcher模块负责请求、限速、错误和日志。请求细节不应该出现在parser或storage里。fetcher.pyimportrequestssession=requests.Session()deffetch_page(url,headers,timeout=10):resp=session.get(url,headers=headers,timeout=timeout)resp.raise_for_status()returnresp.text函数拆解1session连接复用2headers统一传入3raise错误上抛Python爬虫功能教学|05/05项目实战与维护07/20PARSERparser模块只把页面内容转成结构化记录。解析函数必须能用sample.html离线测试。parser.pyfrombs4importBeautifulSoupdefparse_list(html,base_url):soup=BeautifulSoup(html,"html.parser")rows=[]forcardinsoup.select(".item-card"):rows.append(parse_card(card,base_url))returnrows函数拆解1纯函数不发请求2样本便于测试3字段统一字典Python爬虫功能教学|05/05项目实战与维护08/20STORAGEstorage模块负责字段顺序、编码和去重。保存逻辑集中后,替换CSV、JSONL或SQLite更容易。storage.pyimportcsvFIELDS=["title","url","price"]defsave_csv(rows,path):withopen(path,"w",newline="",encoding="utf-8-sig")asf:writer=csv.DictWriter(f,fieldnames=FIELDS)writer.writeheader()writer.writerows(rows)函数拆解1FIELDS稳定字段2encoding中文可读3替换后续可改DBPython爬虫功能教学|05/05项目实战与维护09/20MAINmain.py只组织流程,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论