- XPath,全称 XML Path Language,即 XML 路径语言,它是一门在 XML 文档中查找信息的语言。
- 最初是用来搜寻XML文档的,但同样适用于HTML文档的搜索。所以在做爬虫时完全可以使用 XPath做相应的信息抽取
https://www.w3.org/TR/xpath/
表达式 | 描述 |
---|---|
nodename | 选取此节点的所有子节点 |
/ | 从当前节点选区直接子节点 |
// | 从当前节点选取子孙节点 |
. | 选取当前节点 |
… | 选取当前节点的父节点 |
@ | 选取属性 |
这里列出了XPath的常用匹配规则,示例如下:
- //title[@lang=‘eng’]
这是一个XPath规则,代表的是选择所有名称为title,同时属性lang的值为eng的节点。
windows->python3环境下:pip install lxml
linux环境下:pip3 install lxml
https://www.w3school.com.cn/xpath/index.asp
进行学习
- BeautifulSoup4(简称bs4)翻译成中文就是“美丽的汤”这个奇特的名字来源于《爱丽丝梦游仙境》(这也是为何在其官网会配上奇怪的插图,以及用《爱丽丝》的片段作为测试文本)。
官方文档: https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html
pip install Beautifulsoup4
安装后需要在bs4中导入使用
rom bs4 import BeautifulSoup
使用tip:在使用时需要指定一个“解析器”:
html.parse-python自带,但容错性不够高,对于一些写得不太规范的网页会丢失部分内容
lxml-解析速度快,需额外安装 (推荐使用)
xml-同属 lxml 库,支持 XML 文档
html5lib-最好的容错性,但速度稍慢
# 1. 通过tag标签对象获取文档数据
# r = soup.title
# r = soup.title['abc']
# r = soup.p
# r = soup.p['class']
# r = soup.title.text
# r = soup.p.parent.name
# print(r)
# 2. 通过搜索获取页面中的元素 find,find_all
# r = soup.find('a')
# r = soup.find_all('a')
# r = soup.find('title')
# # print(r,type(r))
# print(r.text)
# print(r.get_text())
# print(r)
# 3.css选择器
# 通过标签 选择元素
r = soup.select('title')
# 通过class类名获取元素
r = soup.select('.title')
# 通过ID名获取元素
r = soup.select('#link2')
# 通过空格 层级关系获取元素
r = soup.select('html body p')
# 通过逗号,并列关系获取元素
r = soup.select('a,title')
# print(r)
正则表达式,就是使用字符,转义字符和特殊字符组成一个规则,
使用这个规则对文本的内容完成一个搜索或匹配或替换的功能、
普通字符: 大小写字母,数字,符合。。。
转义字符:\w \W \d \D \s \S ...
特殊字符:. * ? + ^ $ [] {} ()
匹配模式:I U。。。
示例:
# 使用正则表达式进行匹配的 基本语法
import re
# 定义字符串
vars = 'iloveyou521tosimida'
# 定义正则表达式
reg = 'love'
# 调用正则函数方法
res = re.findall(reg,vars)
print(res)
# 正则模式 re.I 不区分大小写
vars = 'iLOVEyou'
reg = '[a-z]{5,10}'
res = re.search(reg,vars,re.I)
print(res)
抓取方式 | 性能 | 使用难度 |
---|---|---|
lxml | 快 | 简单 |
BeautifulSoup | 慢 | 简单 |
正则表达式 | 快 | 困难 |
这里用了学校的官网
import requests
res=requests.get("https://www.szpt.edu.cn/xyszl.htm")
res.encoding=res.apparent_encoding
print(res.text)
import re
re.findall('(.*?)' ,res.text)
https://movie.douban.com/top250?start=0&filter=
里的- ...
里有电影的排名、电影名、上映年份、国家等信息import re
#re.findall('(.*?) ',res.text)
from bs4 import BeautifulSoup
import requests
headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKib/537.36 (KHTML, like Gecko)"}
res=""
names=[]
years=[]
countrys=[]
types=[]
rates=[]
peoples=[]
for i in range(10):
res=requests.get("https://movie.douban.com/top250?start="+str(i*25)+"&filter",\
headers=headers).text
soup=BeautifulSoup(res,"lxml")
items=soup.find_all("div",class_="info")
for item in items:
names.append(item.span.string)
#names.append(item.find("span",class_="title").string)
#years.append(re.findall(".*?(\d+).*?",item.p.contents[2]))
years.append(item.p.contents[2].split("\xa0")[0].strip())
countrys.append(item.p.contents[2].split("\xa0")[2].strip())
types.append(item.p.contents[2].split("\xa0")[4].strip())
rates.append(item.find("span",class_="rating_num").string)
peoples.append(item.find("div",class_="star").find_all("span")[3].string[:-3])
f=open("movies.csv","w+")
f.write("电影名称,上映年份,国家,影片类型,豆瓣评分,评价人数\n")
for i in range(len(names)):
f.write("{},{},{},{},{},{}\n".format(names[i],years[i],countrys[i],types[i],rates[i],peoples[i]))
f.close()
http://music.163.com/playlist?id=2741819459
import requests
from bs4 import BeautifulSoup
import urllib.request
headers = {
'Referer':'http://music.163.com/',
'Host':'music.163.com',
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/18.17763',
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
}
#url地址
play_url = 'http://music.163.com/playlist?id=2741819459'
#用requests.get()获取页面内容
s = requests.session()
response=s.get(play_url,headers=headers).content
#用beatifulSoup4匹配出对应的歌曲名称和地址
s = BeautifulSoup(response,'lxml')
main = s.find('ul',{'class':'f-hide'})
lists=[]
for music in main.find_all('a'):
list=[]
#print('{}:{}'.format(music.text,music['href']))
musicUrl='https://music.163.com/song/media/outer/url'+music['href'][5:]+'.mp3'
musicName=music.text
#单首歌曲的名字和地址放在list列表中
list.append(musicName)
list.append(musicUrl)
#全部歌曲信息放在lists列表中
lists.append(list)
print(lists)
#下载列表中全部歌曲,并以歌曲名命名下载后的文件,文件位置为当前文件夹
for i in lists:
url=i[1]
name=i[0]
try:
print('下载中',name)
urllib.request.urlretrieve(url,'./%s.mp3'% name)
print('下载成功')
except:
print('下载失败')
# _*_ coding:utf-8 _*_
# 安装两个包
# pip install beautifulsoup4
# pip install urllib3
import os
import urllib
import urllib.request
from bs4 import BeautifulSoup
import re
# 获取内容
def get_content(url):
html = urllib.request.urlopen(url)
content = html.read().decode("utf-8", "ignore")
html.close()
return content
# 获取帖子的页数
def get_page_num(url):
content = get_content(url)
# < a href = "/p/2314539885?pn=31" >尾页 < / a >
pattern = r'尾页'
return int(re.findall(pattern, content)[0])
# 保存图片
def get_images(info, photo_path, npage, photo_format):
if not os.path.exists(photo_path):
os.makedirs(photo_path)
soup = BeautifulSoup(info)
# 找到所有 img 标签 然后后面跟的class = BDE_Image
all_img = soup.find_all("img", class_="BDE_Image")
# 设置计数器
x = 0
for img in all_img:
image_name = photo_path + str(npage) + "_" + str(x) + photo_format
urllib.request.urlretrieve(img["src"], image_name)
x += 1
print("find photo page %d NO. %d" % (npage, x))
return len(all_img)
# 主函数 可改动的参数
# URL——贴吧路径
# photo-path——图片保存的路径
# 图片格式——'.jpg' '.png' '.gif'
if __name__ == "__main__":
url = "https://tieba.baidu.com/p/5997922755"
photo_path = "./imgtieba/"
page_num = get_page_num(url)
for i in range(page_num):
page_url = url + "?pn=" + str(i + 1)
info = get_content(url)
print(get_images(info, photo_path, i + 1, ".gif"))