Xpath,bs4&正则表达式
采用lxml+xpath提取内容
啥是XML?
可扩展标记语言。标记电子文件,使其具有结构性的标记语言。
啥是Xpath?
是XML路径语言,用来确定XML文档中某部分位置;包括七种类型的节点:元素、属性、文本、命名空间、处理指令、注释及文档。可用来在XML文档中对元素和属性进行遍历。
一些Xpath的路径表达式:
Body/p[position()=4] //选择body子元素中的第4个P元素;
Body/p[position()< 3]//选择body子元素中的前2个P元素。
Xpath的书写:
/选取文档节点;
.是当前节点;
…是当前节点的父节点;
@ 选取属性节点。
谓语书写:
/root/child[3] {选取root元素的第三个child子元素,注意,这和数组下标不一样,从1开始计数
//child[@attr] {选取所有具有属性attr的child元素
//child[@attr=“val”]/desc {选取所有属性attr的值为val的child元素的子元素desc
//child[desc] {选取所有的有desc子元素的child
//child[position()>3] {position()是XPath中的一个函数,表示节点的位置
//child[@attr>12] {XPath表达式还可以进行数值比较,该表达式将选取attr属性值大于12的child元素
//child[last()] {last()函数返回节点列表最后的位置,该表达式将选取最后一个child元素
bs4
Beautiful Soup库
是解析、遍历、维护“标签树”的功能库
安装、导入与基础:
pip install beautifulsoup4#安装库功能
from bs4 import BeautifulSoup#调用bs4
import requests
res=request.get(‘待爬取网址’)
demo=r.text #则type(demo)为str
soup=BeautifulSoup(‘<a>html</a>’,’html.parser')#创建Beautiful Soup对象
print(soup.prettify())#美化输出内容,为 HTML文本增加换行,输出更有层次感,标签名会自动分段,看起来很清晰,方便查找并提取需要的信息
列举soup对象的常用功能&上下和同级遍历&查找
soup.a #访问标签a
soup.a.name #访问标签a的名字
soup.a.attrs #访问标签a的属性type为dict
#下行遍历
soup.contents #返回所有子节点
soup.body.content#返回body下的子节点
soup.head#返回head
len(soup.body.content)#返回body下的子节点个数
soup.body.content[1]#返回body下第一个子标签
for child in soup.body.children:#遍历儿子节点
#上行遍历:
for parent in soup.a.parents:#遍历了a标签的父节点
#平行遍历:
soup.a.next_sibling #返回下一个平行标签
soup.a.next_siblings #返回后续所有平行标签
soup.a.previous_sibling #返回上一个平行标签
#bs4的查找方法
soup.find_all(‘标签名称’)
soup.find_all("p","course")#可添加属性检索,更加精准
soup.find('标签名称')#找到第一个,非全部
一个例子:中国大学排名爬取
没搞懂排版的我只能一个标签一个标签地爬…
这里就只放上爬大学名称的code
import requests
from bs4 import BeautifulSoup
import bs4
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"}
url='http://www.zuihaodaxue.cn/zuihaodaxuepaiming2019.html'
res=requests.get(url,headers=headers)
res.encoding=res.apparent_encoding#出现乱码的处理
text=res.text
soup=BeautifulSoup(text,"lxml")#把text建立成一个soup类型对象
items=soup.find("tbody")#找到第一个tbody,里面是所有学校的信息
fenlei=items.find_all("tr",{"class":"alt"})#找到items里面所有具备class:alt特征的标签,相当于把每个学校类拿出来变成一个list
#print(a.prettify())#美化只能对一个子节点去美化,该功能可让一个子节点内部的同级节点分段表示
for a in fenlei:
div=a.find("div",{"align":"left"})#用循环依次从每个学校中取出标签为div,具备align:left特征的内容,这里就是学校名称。
print(div.text)#加.text功能就使div变成str,print之后不会有标签出现
正则表达式
搜索动态文本。
同时查找或替换一组字符串
匹配字符串的全部或部分(主要)
淘宝商品比价定向爬虫
其实没有理解地很好,先放代码,明天再仔细康康
import requests
import re
#库库库
def getHTMLText(url):
"""
请求获取html,(字符串)
:param url: 爬取网址
:return: 字符串
"""
try:
# 添加头信息,
kv = {
'cookie': 'thw=cn; v=0; t=ab66dffdedcb481f77fd563809639584; cookie2=1f14e41c704ef58f8b66ff509d0d122e; _tb_token_=5e6bed8635536; cna=fGOnFZvieDECAXWIVi96eKju; unb=1864721683; sg=%E4%B8%8B3f; _l_g_=Ug%3D%3D; skt=83871ef3b7a49a0f; cookie1=BqeGegkL%2BLUif2jpoUcc6t6Ogy0RFtJuYXR4VHB7W0A%3D; csg=3f233d33; uc3=vt3=F8dBy3%2F50cpZbAursCI%3D&id2=UondEBnuqeCnfA%3D%3D&nk2=u%2F5wdRaOPk21wDx%2F&lg2=VFC%2FuZ9ayeYq2g%3D%3D; existShop=MTU2MjUyMzkyMw%3D%3D; tracknick=%5Cu4E36%5Cu541B%5Cu4E34%5Cu4E3F%5Cu5929%5Cu4E0B; lgc=%5Cu4E36%5Cu541B%5Cu4E34%5Cu4E3F%5Cu5929%5Cu4E0B; _cc_=WqG3DMC9EA%3D%3D; dnk=%5Cu4E36%5Cu541B%5Cu4E34%5Cu4E3F%5Cu5929%5Cu4E0B; _nk_=%5Cu4E36%5Cu541B%5Cu4E34%5Cu4E3F%5Cu5929%5Cu4E0B; cookie17=UondEBnuqeCnfA%3D%3D; tg=0; enc=2GbbFv3joWCJmxVZNFLPuxUUDA7QTpES2D5NF0D6T1EIvSUqKbx15CNrsn7nR9g%2Fz8gPUYbZEI95bhHG8M9pwA%3D%3D; hng=CN%7Czh-CN%7CCNY%7C156; mt=ci=32_1; alitrackid=www.taobao.com; lastalitrackid=www.taobao.com; swfstore=97213; x=e%3D1%26p%3D*%26s%3D0%26c%3D0%26f%3D0%26g%3D0%26t%3D0%26__ll%3D-1%26_ato%3D0; uc1=cookie16=UtASsssmPlP%2Ff1IHDsDaPRu%2BPw%3D%3D&cookie21=UIHiLt3xThH8t7YQouiW&cookie15=URm48syIIVrSKA%3D%3D&existShop=false&pas=0&cookie14=UoTaGqj%2FcX1yKw%3D%3D&tag=8&lng=zh_CN; JSESSIONID=A502D8EDDCE7B58F15F170380A767027; isg=BMnJJFqj8FrUHowu4yKyNXcd2PXjvpa98f4aQWs-RbDvsunEs2bNGLfj8BYE6lWA; l=cBTDZx2mqxnxDRr0BOCanurza77OSIRYYuPzaNbMi_5dd6T114_OkmrjfF96VjWdO2LB4G2npwJ9-etkZ1QoqpJRWkvP.; whl=-1%260%260%261562528831082',
'user-agent': 'Mozilla/5.0'
}
r = requests.get(url, timeout=30, headers=kv)
# r = requests.get(url, timeout=30)
# print(r.status_code)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
return "爬取失败"
#提取待爬取页面信息,r.raise_for_status()方法内部判断r.status_code是否等于200不需要增加额外的if语句,该语句便于利用try-except进行异常处理。
def parsePage(glist, html):
'''
解析网页,搜索需要的信息
:param glist: 列表作为存储容器
:param html: 由getHTMLText()得到的
:return: 商品信息的列表
'''
try:
# 使用正则表达式提取信息
#商品价格
price_list = re.findall(r'', html)
#商品名称
name_list = re.findall(r'', html)
for i in range(len(price_list)):
price = eval(price_list[i].split(":")[1]) #eval()在此可以去掉""
name = eval(name_list[i].split(":")[1])
glist.append([price, name])
except:
print("解析失败")
#提取页面中需要的信息
def printGoodList(glist):
tplt = "{0:^4}\t{1:^6}\t{2:^10}"
print(tplt.format("序号", "商品价格", "商品名称"))
count = 0
for g in glist:
count = count + 1
print(tplt.format(count, g[0], g[1]))
#调整页面输出的格式
#根据页面url的变化寻找规律,构建爬取url
goods_name = "书包" # 搜索商品类型
start_url = "https://s.taobao.com/search?q=" + goods_name
info_list = []
page = 3 # 爬取页面数量
count = 0
for i in range(page):
count += 1
try:
url = start_url + "&s=" + str(44 * i)
html = getHTMLText(url) # 爬取url
parsePage(info_list, html) #解析HTML和爬取内容
print("\r爬取页面当前进度: {:.2f}%".format(count * 100 / page), end="") # 显示进度条
except:
continue
End 今天来不及学会正则表达式了…为今天没学习完白天还摸鱼打了两把王者而深深忏悔…五百斤的胖子说明天会更难,我流泪了…我挺好的…就是头有点冷…
PS:立flag,明天一定MOOC视频学习呜呜呜