1。urllib库1。1基本使用 使用urllib来获取百度首页的源码importurllib。request1、定义一个url就是你要访问的地址urlhttp:www。baidu。com2、模拟浏览器向服务器发送请求response响应responseurllib。request。urlopen(url)3、获取响应中的页面的源码contentresponse。read()。decode(utf8)4、打印数据print(content) read方法,返回的是字节形式的二进制数据,我们要将二进制的数据转换为字符串,需解码:decode(‘编码的格式’)1。21个类型和6个方法importurllib。requesturlhttp:www。baidu。com模拟浏览器向服务器发送请求responseurllib。request。urlopen(url)一个类型:response是HTTPResponse的类型print(type(response))按照一个字节一个字节的去读contentresponse。read()print(content)返回多少个字节contentresponse。read(5)print(content)读取一行contentresponse。readline()print(content)一行一行读取直至结束contentresponse。readlines()print(content)返回状态码如果是200了那么就证明我们的逻辑没有错print(response。getcode())返回的是url地址print(response。geturl())获取是一个状态信息print(response。getheaders()) 一个类型:HTTPResponse六个方法:read、readline、readlines、getcode、geturl、getheaders1。3下载importurllib。request下载网页urlpagehttp:www。baidu。comurl代表的是下载的路径filename文件的名字urllib。request。urlretrieve(urlpage,baidu。html)下载图片urlimghttps:img1。baidu。comitu3004965690,4089234593fm26fmtautogp0。jpgurllib。request。urlretrieve(urlurlimg,filenamelisa。jpg)下载视频urlvideohttps:vd3。bdstatic。commdamhkku4ndaka5etk31080pcaeh2641629557146541497769mdamhkku4ndaka5etk3。mp4?vfromshkapphaokantuchengauthkey1629687514007ed57ed7d1168bb1f06d18a4ea214300bcevodchannelsearchboxfeedpd1pt3abtesturllib。request。urlretrieve(urlvideo,hxekyyds。mp4) 在python中,可以写变量的名字,也可以直接写值1。4请求对象的定制importurllib。requesturlhttps:www。baidu。comheaders{UserAgent:Mozilla5。0(WindowsNT10。0;Win64;x64)AppleWebKit537。36(KHTML,likeGecko)Chrome92。0。4515。159Safari537。36}因为urlopen方法中不能存储字典所以headers不能传递进去请求对象的定制requesturllib。request。Request(urlurl,headersheaders)responseurllib。request。urlopen(request)contentresponse。read()。decode(utf8)print(content)1。5get请求的quote方法 get请求参数,如果是中文,需要对中文进行编码,如下面这样,如果不编码会报错。 需求获取https:www。baidu。coms?wd周杰伦的网页源码编码后如下:https:www。baidu。coms?wdE591A8E69DB0E4BCA6importurllib。requestimporturllib。parseurlhttps:www。baidu。coms?wd请求对象的定制为了解决反爬的第一种手段headers{UserAgent:Mozilla5。0(WindowsNT10。0;Win64;x64)AppleWebKit537。36(KHTML,likeGecko)Chrome92。0。4515。159Safari537。36}将周杰伦三个字变成unicode编码的格式,需要依赖于urllib。parsenameurllib。parse。quote(周杰伦)将转码后的字符串拼接到路径后面urlurlname请求对象的定制requesturllib。request。Request(urlurl,headersheaders)模拟浏览器向服务器发送请求responseurllib。request。urlopen(request)获取响应的内容contentresponse。read()。decode(utf8)打印数据print(content) quote适用于将中文转码成Unicode编码1。6get请求的urlencode方法 urlencode应用场景:多个参数的时候。如下 https:www。baidu。coms?wd周杰伦sex男获取https:www。baidu。coms?wdE591A8E69DB0E4BCA6sexE794B7的网页源码importurllib。requestimporturllib。parsebaseurlhttps:www。baidu。coms?data{wd:周杰伦,sex:男,location:中国台湾省}newdataurllib。parse。urlencode(data)请求资源路径urlbaseurlnewdataheaders{UserAgent:Mozilla5。0(WindowsNT10。0;Win64;x64)AppleWebKit537。36(KHTML,likeGecko)Chrome92。0。4515。159Safari537。36}请求对象的定制requesturllib。request。Request(urlurl,headersheaders)模拟浏览器向服务器发送请求responseurllib。request。urlopen(request)获取网页源码的数据contentresponse。read()。decode(utf8)打印数据print(content)1。7post请求importurllib。requestimporturllib。parseurlhttps:fanyi。baidu。comsugheaders{UserAgent:Mozilla5。0(WindowsNT10。0;Win64;x64)AppleWebKit537。36(KHTML,likeGecko)Chrome92。0。4515。159Safari537。36}data{kw:spider}post请求的参数,必须要进行编码dataurllib。parse。urlencode(data)。encode(utf8)requesturllib。request。Request(urlurl,datadata,headersheaders)模拟浏览器向服务器发送请求responseurllib。request。urlopen(request)获取响应的数据contentresponse。read()。decode(utf8)字符串》json对象importjsonobjjson。loads(content)print(obj) post请求的参数必须要进行编码:dataurllib。parse。urlencode(data)undefined编码之后必须调用encode方法:dataurllib。parse。urlencode(data)。encode(‘utf8’)undefinedpost的请求的参数,是不会拼接在url的后面的,而是需要放在请求对象定制的参数中:undefinedrequesturllib。request。Request(urlurl,datadata,headersheaders)1。8异常importurllib。requestimporturllib。errorurlhttp:www。doudan1。comheaders{UserAgent:Mozilla5。0(WindowsNT10。0;Win64;x64)AppleWebKit537。36(KHTML,likeGecko)Chrome92。0。4515。159Safari537。36}try:requesturllib。request。Request(urlurl,headersheaders)responseurllib。request。urlopen(request)contentresponse。read()。decode(utf8)print(content)excepturllib。error。HTTPError:print(系统正在升级)excepturllib。error。URLError:print(我都说了系统正在升级)1。9handler 为什么要学习handler?urllib。request。urlopen(url)不能定制请求头urllib。request。Request(url,headers,data)可以定制请求头Handler:定制更高级的请求头(随着业务逻辑的复杂请求对象的定制已经满足不了我们的需求,动态cookie和代理不能使用请求对象的定制)需求使用handler来访问百度获取网页源码importurllib。requesturlhttp:www。baidu。comheaders{UserAgent:Mozilla5。0(WindowsNT10。0;Win64;x64)AppleWebKit537。36(KHTML,likeGecko)Chrome92。0。4515。159Safari537。36}requesturllib。request。Request(urlurl,headersheaders)handlerbuildopeneropen(1)获取hanlder对象handlerurllib。request。HTTPHandler()(2)获取opener对象openerurllib。request。buildopener(handler)(3)调用open方法responseopener。open(request)contentresponse。read()。decode(utf8)print(content)1。10代理 为什么需要代理?因为有的网站是禁止爬虫的,如果用真实的ip去爬虫,容易被封掉。importurllib。requesturlhttp:www。baidu。coms?wdipheaders{UserAgent:Mozilla5。0(WindowsNT10。0;Win64;x64)AppleWebKit537。36(KHTML,likeGecko)Chrome92。0。4515。159Safari537。36}请求对象的定制requesturllib。request。Request(urlurl,headersheaders)模拟浏览器访问服务器responseurllib。request。urlopen(request)proxies{http:118。24。219。151:16817}handlerbuildopeneropenhandlerurllib。request。ProxyHandler(proxiesproxies)openerurllib。request。buildopener(handler)responseopener。open(request)获取响应的信息contentresponse。read()。decode(utf8)保存withopen(daili。html,w,encodingutf8)asfp:fp。write(content) 代理可以使用:快代理。可以使用代理池来代替一个代理 2。解析技术2。1xpathxpath安装及加载 1。安装lxml库 pipinstalllxmlihttps:pypi。douban。comsimple 2。导入lxml。etree fromlxmlimportetree 3。etree。parse()解析本地文件 htmltreeetree。parse(‘XX。html’) 4。etree。HTML()服务器响应文件 htmltreeetree。HTML(response。read()。decode(‘utf8’) 5。解析获取DOM元素 htmltree。xpath(xpath路径)按照xpath的chrome插件,使用ctrlshiftx打开插件xpath基本语法 1。路径查询 :查找所有子孙节点,不考虑层级关系undefined:找直接子节点 2。谓词查询 pidundefinedpidmaincontent 3。属性查询 class 4。模糊查询 pcontains(id,he)undefinedpstartswith(id,he) 5。内容查询 ph1text() 6。逻辑运算 pidheadandclasssdownundefinedtitleprice 示例:fromlxmlimportetreexpath解析本地文件treeetree。parse(test。html)查找ul下面的lililisttree。xpath(bodyulli)查找所有有id的属性的li标签,text()获取标签中的内容lilisttree。xpath(ulli〔id〕text())找到id为l1的li标签注意引号的问题lilisttree。xpath(ulli〔idl1〕text())查找到id为l1的li标签的class的属性值litree。xpath(ulli〔idl1〕class)查询id中包含l的li标签lilisttree。xpath(ulli〔contains(id,l)〕text())查询id的值以l开头的li标签lilisttree。xpath(ulli〔startswith(id,c)〕text())查询id为l1和class为c1的lilisttree。xpath(ulli〔idl1andclassc1〕text())lilisttree。xpath(ulli〔idl1〕text()ulli〔idl2〕text())2。2JsonPath JsonPath只能解析本地文件。jsonpath的安装及使用 pip安装: pipinstalljsonpath jsonpath的使用: objjson。load(open(‘json文件’,‘r’,encoding‘utf8’))undefinedretjsonpath。jsonpath(obj,‘jsonpath语法’) 示例:{store:{book:〔{category:修真,author:六道,title:坏蛋是怎样练成的,price:8。95},{category:修真,author:天蚕土豆,title:斗破苍穹,price:12。99},{category:修真,author:唐家三少,title:斗罗大陆,isbn:0553213113,price:8。99},{category:修真,author:南派三叔,title:星辰变,isbn:0395193958,price:22。99}〕,bicycle:{author:老马,color:黑色,price:19。95}}} 解析上面的json数据importjsonimportjsonpathobjjson。load(open(jsonpath。json,r,encodingutf8))书店所有书的作者authorlistjsonpath。jsonpath(obj,。store。book〔〕。author)所有的作者authorlistjsonpath。jsonpath(obj,。。author)store下面的所有的元素taglistjsonpath。jsonpath(obj,。store。)store里面所有东西的pricepricelistjsonpath。jsonpath(obj,。store。。price)第三个书bookjsonpath。jsonpath(obj,。。book〔2〕)最后一本书bookjsonpath。jsonpath(obj,。。book〔(。length1)〕)前面的两本书booklistjsonpath。jsonpath(obj,。。book〔0,1〕)booklistjsonpath。jsonpath(obj,。。book〔:2〕)条件过滤需要在()的前面添加一个?过滤出所有的包含isbn的书。booklistjsonpath。jsonpath(obj,。。book〔?(。isbn)〕)哪本书超过了10块钱booklistjsonpath。jsonpath(obj,。。book〔?(。price10)〕)2。3BeautifulSoup基本介绍BeautifulSoup简称:bs4什么是BeatifulSoup?BeautifulSoup,和lxml一样,是一个html的解析器,主要功能也是解析和提取数据优缺点 缺点:效率没有lxml的效率高 优点:接口设计人性化,使用方便安装以及创建安装 pipinstallbs4ihttps:pypi。douban。comsimple导入 frombs4importBeautifulSoup创建对象服务器响应的文件生成对象soupBeautifulSoup(response。read()。decode(),‘lxml’)本地文件生成对象soupBeautifulSoup(open(‘1。html’),‘lxml’) 注意:默认打开文件的编码格式gbk所以需要指定打开编码格式节点定位 1。根据标签名查找节点 soup。a只能找到第一个asoup。a。name soup。a。attrs 2。函数find(返回一个对象) find(‘a’):只找到第一个a标签 find(‘a’,title‘名字’) find(‘a’,class‘名字’)findall(返回一个列表) findall(‘a’):查找到所有的a findall(〔‘a’,‘span’〕)返回所有的a和span findall(‘a’,limit2)只找前两个aselect(根据选择器得到节点对象)【】element:p。class:。firstnameid:firstname属性选择器:undefined〔attribute〕:lisoup。select(‘li〔class〕’)undefined〔attributevalue〕:lisoup。select(‘li〔classhengheng1〕’)层级选择器:undefinedpp后代选择器undefinedpp子代选择器:某标签的第一级子标签undefinedp,pp或p标签的所有的对象节点信息获取节点内容:适用于标签中嵌套标签的结构 obj。string obj。gettext()【推荐】节点的属性 tag。name:获取标签名 tag。attrs:将属性值作为一个字典返回获取节点属性 obj。attrs。get(‘title’)【常用】 obj。get(‘title’) obj〔‘title’〕 示例:!DOCTYPEhtmlhtmllangenheadmetacharsetUTF8titleTitletitleheadbodyulliidl1张三liliidl2李四lili王五li尚硅谷span嘿嘿嘿spanul百度span哈哈哈spanpidp1classp1呵呵呵bodyhtml 使用BeautifulSoup解析上面的htmlfrombs4importBeautifulSoup默认打开的文件的编码格式是gbk,所以在打开文件的时候需要指定编码soupBeautifulSoup(open(bs4的基本使用。html,encodingutf8),lxml)根据标签名查找节点,找到的是第一个符合条件的数据print(soup。a)获取标签的属性和属性值print(soup。a。attrs)bs4的一些函数(1)find:返回的是第一个符合条件的数据print(soup。find(a))根据title的值来找到对应的标签对象print(soup。find(a,titlea2))根据class的值来找到对应的标签对象注意的是class需要添加下划线print(soup。find(a,classa1))(2)findall返回的是一个列表,并且返回了所有的a标签print(soup。findall(a))如果想获取的是多个标签的数据那么需要在findall的参数中添加的是列表的数据print(soup。findall(〔a,span〕))limit的作用是查找前几个数据print(soup。findall(li,limit2))(3)select(推荐)select方法返回的是一个列表,并且会返回多个数据print(soup。select(a))可以通过。代表class我们把这种操作叫做类选择器print(soup。select(。a1))print(soup。select(l1))属性选择器:通过属性来寻找对应的标签查找到li标签中有id的标签print(soup。select(li〔id〕))查找到li标签中id为l2的标签print(soup。select(li〔idl2〕))层级选择器后代选择器:找到的是p下面的liprint(soup。select(pli))子代选择器:某标签的第一级子标签print(soup。select(pulli))找到a标签和li标签的所有的对象print(soup。select(a,li))获取节点内容objsoup。select(d1)〔0〕如果标签对象中,只有内容,那么string和gettext()都可以使用如果标签对象中,除了内容还有标签,那么string就获取不到数据而gettext()是可以获取数据推荐使用gettext()print(obj。string)print(obj。gettext())节点的属性objsoup。select(p1)〔0〕name是标签的名字print(obj。name)将属性值左右一个字典返回print(obj。attrs)获取节点的属性print(obj。attrs。get(class))print(obj。get(class))print(obj〔class〕)