目录
day04
1.requests模块方法
- get()参数
- 查询参数:params - 字典
- 代理:proxies - 字典
- 普通代理:{'协议':"协议://ip地址:端口号"}
- 私密代理:{'协议':"协议://用户名:密码@ip地址:端口号"}
- Web客户端验证:auth - 元组
auth = ('tarenacode','code_2014') - SSL证书:verify -> 默认True
- timeout
- post()方法
- data - 字典,Form表单数据
- 响应对象属性
- text - 字符串
- encoding - res.enconding = 'utf-8'
- content -> 字节流
- status_code - 服务器响应码
2.数据持久化储存
- MySQL流程
- db = pymysql.connect('local',...'库名',charset='uft8')
- cursor = db.cursor()
- cursor.execute("sql命令",[])
- db.commit()
- cursor.close()
- db.close()
- mongodb流程
- conn = pymongo.MongoClient('localhost',27017)
- db = conn.库名
- myset = db.集合名
- myset.insert(字典)
终端操作- mongo
- show dbs
- use 库名
- show tables
- db.集合名.find().pretty()
3.Handler处理器(urllib库中)
- 使用流程
- 创建Handler:ProxyHandler(普通代理IP)
- 创建opener:build_opener(Handler)
- 发请求:opener.open(requeust)
- ProxyHandler
- ph = urllib.request.ProxyHandler({'http':'IP: ..'})
- opener = urllib.request.bulid_opener(ph)
- req = urllib.request.Request(url,headers=headers...)
- res = opener.open(req)
- html = res.read().decode('utf-8')
- Handler处理器分类
- ProxyHandler({普通代理IP})
- ProxyBasicAuthHandler(密码管理器对象)
- HTTPBasicAuthHandler(密码管理器对象)
- 流程
- 创建
pwdmg = urllib.request.HTTPPasswordMgrWith...() - 添加认证信息
pwdmg.add_password(None,{"协议":"IP:..},"user","pwd") - Handler开始
- 创建
day04
1.xpath工具(解析)
- xpath
在xml文档中查找信息的语言,同样适用于HTML文档的检索 - xpath辅助工具
- Chrome插件:XPath Helper
- 打开:Ctrl + Shift + 大写X
- 关闭:Ctrl + Shift + 大写X
- Firefox插件:Xpath checker
- XPath表达式编辑工具:XML quire
- Chrome插件:XPath Helper
- xpath匹配规则
- 匹配演示
- 查找bookstore下所有节点:/bookstore
- 查找所有的book节点://book
- 查找所有book下的title节点中,lang属性为‘en’的节点://book/title[@lang="en"]
- 查找bookstore下的第2个book节点下的title节点:/bookstore/book[2]/title/text()
<?xml version="1.0" encoding="ISO-8859-1"?> <bookstore> <book> <title lang="en">Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book> <book> <title lang="chs">Python</title> <author>Joe</author> <year>2018</year> <price>49.99</price> </book> </bookstore>
- 选取节点
/ : 从根节点开始选取
// : 从整个文档中查找节点
@ : 选取某个节点的属性
//title[@lang="en"] - @的使用
- 选取1个节点://title[@lang="en"]
- 选取n个节点://title[@lang]
- 选取节点的属性值://title/@lang
- 匹配多路径
- 符号:|
- 获取所有book节点下的title节点和price节点
//book/title | //book/price
- 函数
- contains():匹配一个属性值中包含某些字符串的节点
//title[contains(@lang,'e')] - text()
//title[contains(@lang,'e')]/text()
- contains():匹配一个属性值中包含某些字符串的节点
- 匹配演示
2.lxml库及xpath使用
- lxml库:HTML/XML解析库
- 安装
python -m pip install 1xml
conda install lxml - 使用流程
- 导模块
from 1xml import etree - 利用lxml库的etree模块创建解析对象
parseHtml = etree.HTML(html) - 解析对象调用xpath工具定位节点信息
r_list = parseHtml.xpath('xpath表达式')
##只要调用了xpath,结果一定是列表
- 导模块
- 示例:
from lxml import etree html = """<div class="wrapper"> <i class="iconfont icon-back" id="back"></i> <a href="/" id="channel">新浪社会</a> <ul id="nav"> <li><a href="http://domestic.firefox.sina.com/" title="国内">国内</a></li> <li><a href="http://world.firefox.sina.com/" title="国际">国际</a></li> <li><a href="http://mil.firefox.sina.com/" title="军事">军事</a></li> <li><a href="http://photo.firefox.sina.com/" title="图片">图片</a></li> <li><a href="http://society.firefox.sina.com/" title="社会">社会</a></li> <li><a href="http://ent.firefox.sina.com/" title="娱乐">娱乐</a></li> <li><a href="http://tech.firefox.sina.com/" title="科技">科技</a></li> <li><a href="http://sports.firefox.sina.com/" title="体育">体育</a></li> <li><a href="http://finance.firefox.sina.com/" title="财经">财经</a></li> <li><a href="http://auto.firefox.sina.com/" title="汽车">汽车</a></li> </ul> <i class="iconfont icon-liebiao" id="menu"></i> </div>""" # 构造解析对象 parseHtml = etree.HTML(html) # 利用解析对象调用xpath匹配 r1 = parseHtml.xpath('//a/@href') #print(r1) # 获取 / r2 = parseHtml.xpath('//a[@id="channel"]/@href') #print(r2) # 获取非 / r3 = parseHtml.xpath('//ul[@id="nav"]//a/@href') #print(r3) # 获取所有 a 节点的文本内容 r4 = parseHtml.xpath('//a/text()') #print(r4) # 获取 图片、军事 ... r5 = parseHtml.xpath('//ul[@id="nav"]//a') for i in r5: print(i.text)
扫描二维码关注公众号,回复: 3832914 查看本文章 - 如何获取节点对象的内容
节点对象.text - 案列1:获取百度贴吧帖子里面所有的图片
- 目标:抓取指定贴吧所有图片
- 思路
- 获取贴吧主页URL,下一页:找URL规律
- 获取1页中每个帖子的URL
- 对每个帖子URL发请求,获取帖子里图片URL
- 对图片URL发请求,以wb方式写入本地文件
- 步骤
- 获取贴吧主页URL
http://tieba.baidu.com/f? + 查询参数 - 找到页面中所有帖子的URL
src:完整链接
href:和主URL进行拼接
/p/5926064184
http://tieba.baidu.com/p/5926064184
xpath匹配
写法1: //div[@class="col2_right j_threadlist_li_right"]/div/div/a/@href
写法2(推荐): //div[@class="t_con cleafix"]/div/div/div/a/@href - 找每个帖子中图片URL
Xpath匹配:
//img[@class="BDE_Image"]/@src - 代码实现
'''02_百度贴吧图片抓取案例.py''' import requests from lxml import etree class BaiduImageSpider: def __init__(self): self.headers = {"User-Agent":"Mozilla/5.0"} self.baseurl = "http://tieba.baidu.com" self.pageurl = "http://tieba.baidu.com/f?" # 获取所有帖子URL列表 def getPageUrl(self,params): res = requests.get(self.pageurl,params=params,headers=self.headers) res.encoding = "utf-8" html = res.text # 构建解析对象 parseHtml = etree.HTML(html) # 帖子链接列表 t_list = parseHtml.xpath('//div[@class="t_con cleafix"]/div/div/div/a/@href') # t_list : ['/p/233432','/p/2039820',..] #print(t_list) for t_link in t_list: # 拼接帖子完整链接 t_link = self.baseurl + t_link self.getImageUrl(t_link) # 获取帖子中图片URL列表 def getImageUrl(self,t_link): res = requests.get(t_link,headers=self.headers) res.encoding = "utf-8" html = res.text # 构造解析对象 parseHtml = etree.HTML(html) img_list = parseHtml.xpath('//img[@class="BDE_Image"]/@src') # print(img_list) for img_link in img_list: self.writeImage(img_link) # 保存到本地 def writeImage(self,img_link): # 获取图片的bytes res = requests.get(img_link,headers=self.headers) res.encoding = "utf-8" html = res.content # filename filename = img_link[-12:] with open(filename,"wb") as f: f.write(html) print("%s下载成功" % filename) # 主函数 def workOn(self): name = input("请输入贴吧名:") begin = int(input("请输入起始页:")) end = int(input("请输入终止页:")) for n in range(begin,end+1): pn = (n-1)*50 params = { "kw":name, "pn":str(pn) } self.getPageUrl(params) if __name__ == "__main__": spider = BaiduImageSpider() spider.workOn()
- 获取贴吧主页URL
- 案例2:嗅事百科 - xpath
- 目标:用户名称
- 步骤
- 找URL
https://www.qiushibaike.com/8hr/page/1/ - xpath匹配
- 基准xpath://div[contains(@id,"qiushi_tag_")]
用户昵称:./div/a/h2
段子内容:.//div[@class="content"]/span
好笑数量:.//i
评论数量:.//i
- 基准xpath://div[contains(@id,"qiushi_tag_")]
- 找URL
- 写代码:
'''03_糗事百科案例.py''' import requests from lxml import etree import pymongo class QiuShiSpider: def __init__(self): self.url = "https://www.qiushibaike.com/8hr/page/1/" self.headers = {"User-Agent":"Mozilla/5.0"} self.conn = pymongo.MongoClient("localhost",27017) self.db = self.conn.Baikedb self.myset = self.db.baikeset def getPage(self): res = requests.get(self.url,headers=self.headers) res.encoding = "utf-8" html = res.text self.parsePage(html) def parsePage(self,html): parseHtml = etree.HTML(html) # 基准xpath,每个段子的列表 base_list = parseHtml.xpath('//div[contains(@id,"qiushi_tag_")]') # 遍历每个段子的节点对象(base) for base in base_list: # 用户昵称 username = base.xpath('./div/a/h2') if len(username) == 0: username = "匿名用户" else: username = username[0].text # 段子内容 content = base.xpath('.//div[@class="content"]/span')[0].text # 好笑数量 # [<element.好笑数量>,<eleme.评论>,<element...>] laughNum = base.xpath('.//i')[0].text # 评论数量 pingNum = base.xpath('.//i')[1].text d = { "username":username.strip(), "content":content.strip(), "laughNum":laughNum.strip(), "pingNum":pingNum.strip() } self.myset.insert(d) print("存入数据库成功") if __name__ == "__main__": spider = QiuShiSpider() spider.getPage()
- 安装
3.动态网站数据抓取
- Ajax动态加载
- 特点:滚动鼠标滑轮时加载
- 抓包工具:查询参数在 WebForms - QueryString
今日示例