千锋教育-做有情怀、有良心、有品质的职业教育机构

手机站
千锋教育

千锋学习站 | 随时随地免费学

千锋教育

扫一扫进入千锋手机站

领取全套视频
千锋教育

关注千锋学习站小程序
随时随地免费学习课程

当前位置:首页  >  技术干货  > xpath与美食结合据说更香哦

xpath与美食结合据说更香哦

来源:千锋教育
发布人:qyf
时间: 2022-09-08 17:47:29 1662630449

  我们今天写的爬虫内容是xpath,我们通过美食页面的分析带领大家学习xpath。

  先来介绍一下xpath。 XPath即为XML路径语言,它是一种用来确定XML(标准通用标记语言的子集)文档中某部分位置的语言。XPath基于XML的树状结构,有不同类型的节点,包括元素节点,属性节点和文本节点,提供在数据结构树中找寻节点的能力。 跟BeautifulSoup4一样都是用来解析页面内容的工具,只不过使用方式有所不同而已。

  要想使用xpath,需要安装lxml: pip install lxml

  案例分析

  下面我们通过豆果网精选美食https://www.douguo.com/jingxuan/0来带领大家学习使用xpath。

Picture

Picture

 

  我们要获取菜谱的名称、作者、浏览量、收藏量、图片等信息,每页中有24个菜谱推荐。

  看一下文章的节点情况:

Picture(1)

  可以发现有多个li【类选择器是item的】标签,每个li里面包含两部分内容过:【a标签和div标签】

  a标签中包含的是图片和视频内容过,

  div标签中包含的信息是:菜谱的名称、作者、浏览量、收藏量

  因此我们通过节点找到id=jxlist的ul标签,就可以获取里面的多个li标签。

  xpath节点选取语法

  在介绍bs4的时候,我们已经给大家介绍了节点的概念,比如父节点、子节点、同胞节点、先辈节点和后代节点等。

  XPath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的。

  常用的路径表达式有:

Picture(2)

  但是往往在查找的时候,我们需要获取某个特定的节点,则需要配合下面的方式即:被嵌在方括号内,用来查找某个特定的节点或包含某个制定的值的节点。

Picture(3)

  另外还可以在使用xpath的时候使用通配符和功能函数

Picture(4)

Picture(5)

  案例使用

  使用requests获取网页信息

  import requests

  headers = {

  'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Safari/537.36'}

  response = requests.get('https://www.douguo.com/jingxuan/0', headers=headers)

  # 为了写xpath内容,我们先将内容保存到本地,然后爬取多页内容

  with open('jingxuan.html', 'wb') as stream:

  stream.write(response.content)

  我们分析页面内容并使用xpath,

  获取美食的详情页链接

Picture(6)

  可以发现详情页的链接在a标签的href属性中,通过xpath获取可以使用:

  //ul[@id="jxlist"]/li/a/@href

  表示获取id叫jxlist的ul标签,注意此处使用了//,每一层的/表示一层关系

  完整代码:

  from lxml import etree

  # 读取保存在本地的网页,进行xpath解析

  with open('jingxuan.html', 'r') as stream:

  all = stream.read()

  html = etree.HTML(all)

  links = html.xpath('//ul[@id="jxlist"]/li/a/@href')

  print(links)

  结果提取出了所有li中的详情页链接,当前如果访问要添加前缀(https://www.douguo.com)进行拼接:

  ['/cookbook/3102422.html', '/cookbook/3102421.html', '/cookbook/3102419.html', ..... ]

  美食图片的获取,美食图片的链接在a标签的img标签中,所以代码要改成:

  images = html.xpath('//ul[@id="jxlist"]/li/a/img/@src')

  print(images)

  获取了每个美食的图片链接,结果如下:

  ['https://cp1.douguo.com/upload/caiku/a/6/a/400x266_a6502b09c35f4331a5c4b812f5e77bba.jpeg', 'https://cp1.douguo.com/upload/caiku/7/6/a/400x266_7639e7ea6394437042e9b2f77414f84a.jpg',

  ......

  ]

  菜名的获取,有两种方式:

  在a标签的alt属性中获取

  //ul[@id="jxlist"]/li/a/@alt

  在div的第一个a标签中获取

  //ul[@id="jxlist"]/li/div/a[1]/text()

Picture(7)

  本次使用的是第二种方式,其中a[1]表示div中的第一个div标签。

  names = html.xpath('//ul[@id="jxlist"]/li/div/a[1]/text()')

  print(names)

  结果:

  ['麻辣小龙虾', '#仙女们的私藏鲜法大PK#家庭版健康双牛汉堡', '#舌尖上的端午#蓝莓酱', '蒜蓉虾', '奶香小面包',......]

  发表用户的获取

  用户名在div的第二个a标签中,但是发现a标签不仅有文本还有img标签。按照上面的方式获取(注意文本的获取使用text())

  //ul[@id="jxlist"]/li/div/a[2]/text()

  发现结果,将文本的换行和空格内容都包含在里面了,而且每个文本的前面都有一个空内容:

Picture(8)

  于是我们需要进行正则的替换和获取有用信息。

  import re

  users = html.xpath('//ul[@id="jxlist"]/li/div/a[2]/text()')

  pattern = re.compile(r"\n+|\s+", re.S) # 查找\n和\s进行替换

  users = [pattern.sub('', users[u]) for u in range(1,len(users),2)] # 删除第一个空内容

  print(users)

  结果:

  ['好吃的豆苗', '马赛克姑凉', '浅夏°淡雅', '清雅wuda', '肉乎乎的小瘦子', 'dreamer...', '拒绝添加剂',......]

  浏览量和收藏量的获取方式是一样的,分别在两个span标签中

Picture(9)

  //ul[@id="jxlist"]/li/div/div/span[1]/text() 获取浏览量

  //ul[@id="jxlist"]/li/div/div/span[2]/text() 获取收藏量

  代码如下:

  views = html.xpath('//ul[@id="jxlist"]/li/div/div/span[1]/text()')

  print(views)

  collects = html.xpath('//ul[@id="jxlist"]/li/div/div/span[2]/text()')

  print(collects)

  运行结果:

  ['3656', '1.5万', '1.5万', '3158', '2729', '1.2万', '2.0万', ...... ]

  ['78', '431', '504', '83', '32', '245', '484',......]

  完整代码

  以下代码添加了分页的内容,分页的特点是:

  https://www.douguo.com/jingxuan/0 第一页

  https://www.douguo.com/jingxuan/24 第二页

  https://www.douguo.com/jingxuan/48 第二页

  .....

  import requests

  import re

  import csv

  from lxml import etree

  def get_html(page):

  headers = {

  'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Safari/537.36'}

  response = requests.get('https://www.douguo.com/jingxuan/' + str(page), headers=headers)

  return response.text

  def parse_html(content):

  html = etree.HTML(content)

  links = html.xpath('//ul[@id="jxlist"]/li/a/@href')

  images = html.xpath('//ul[@id="jxlist"]/li/a/img/@src')

  names = html.xpath('//ul[@id="jxlist"]/li/div/a[1]/text()')

  users = html.xpath('//ul[@id="jxlist"]/li/div/a[2]/text()')

  pattern = re.compile(r"\n+|\s+", re.S)

  users = [pattern.sub('', users[u]) for u in range(1, len(users), 2)]

  views = html.xpath('//ul[@id="jxlist"]/li/div/div/span[1]/text()')

  collects = html.xpath('//ul[@id="jxlist"]/li/div/div/span[2]/text()')

  return zip(names, links, users, views, collects, images)

  def save_data(foods):

  with open('foods.csv', 'a') as stream:

  writer = csv.writer(stream)

  writer.writerows(foods)

  if __name__ == '__main__':

  for i in range(6):

  page = i*24

  content = get_html(page)

  foods = parse_html(content)

  save_data(foods)

  print(f"第{i+1}页保存成功!")

tags:
声明:本站稿件版权均属千锋教育所有,未经许可不得擅自转载。
10年以上业内强师集结,手把手带你蜕变精英
请您保持通讯畅通,专属学习老师24小时内将与您1V1沟通
免费领取
今日已有369人领取成功
刘同学 138****2860 刚刚成功领取
王同学 131****2015 刚刚成功领取
张同学 133****4652 刚刚成功领取
李同学 135****8607 刚刚成功领取
杨同学 132****5667 刚刚成功领取
岳同学 134****6652 刚刚成功领取
梁同学 157****2950 刚刚成功领取
刘同学 189****1015 刚刚成功领取
张同学 155****4678 刚刚成功领取
邹同学 139****2907 刚刚成功领取
董同学 138****2867 刚刚成功领取
周同学 136****3602 刚刚成功领取

上一篇

HTML结构分析

下一篇

selenium简介
相关推荐HOT