xpath工具(解析)

  • xpath

    • 在XML文档中查找信息的语言,同样适用于HTML文档的检索
  • xpath辅助工具
    • Chrome插件 :XPath Helper

      • 打开 :Ctrl + Shift + X
      • 关闭 :Ctrl + Shift + X
    • Firefox插件 :XPath checker
    • XPath表达式编辑工具 :XML quire

xpath匹配规则

  • 匹配演示

    1. 查找bookstore下所有节点:/bookstore
    2. 查找所有的book节点://book
    3. 查找所有book下的title节点中,lang属性为"en"的节点
      • //book/title[@lang="en"]
    4. 查找bookstore下的第2个book节点下的title节点:
      • /bookstore/book[2]/title/text()
  • 选取节点
    • / :从根节点开始选取
    • //:从整个文档中查找节点
      • //price 、 /bookstore/book//price
    • @ :选取某个节点的属性
      • //title[@lang="en"]
  • @的使用
    • 选取1个节点://title[@lang="en"]
    • 选取N个节点://title[@lang]
    • 选取节点的属性值://title/@lang
      • <a class=....,src="http://..."
  • 匹配多路径
    • 符号:|
    • 获取所有book节点下的 title节点和price节点
      • //book/title | //book/price
  • 函数
    • contains():匹配一个属性值中包含某些字符串的节点

      • //title[contains(@lang,"e")]
    • text()
      • //title[contains(@lang,"e")]/text()

lxml库及xpath使用

lxml库 :HTML/XML解析库

  • 安装

    • python -m pip install lxml
    • conda install lxml
  • 使用流程
    1. 导模块

      • from lxml import etree
    2. 利用lxml库的etree模块创建解析对象
      • parseHtml = etree.HTML(html)
    3. 解析对象调用xpath工具定位节点信息
      • r_list = parseHtml.xpath('xpath表达式')

只要调用了xpath,结果一定是列表

4. 如何获取节点对象的内容

- 节点对象.text

  1. from lxml import etree
  2. html = """<div class="wrapper">
  3. <i class="iconfont icon-back" id="back"></i>
  4. <a href="/" id="channel">新浪社会</a>
  5. <ul id="nav">
  6. <li><a href="http://domestic.firefox.sina.com/" title="国内">国内</a></li>
  7. <li><a href="http://world.firefox.sina.com/" title="国际">国际</a></li>
  8. <li><a href="http://mil.firefox.sina.com/" title="军事">军事</a></li>
  9. <li><a href="http://photo.firefox.sina.com/" title="图片">图片</a></li>
  10. <li><a href="http://society.firefox.sina.com/" title="社会">社会</a></li>
  11. <li><a href="http://ent.firefox.sina.com/" title="娱乐">娱乐</a></li>
  12. <li><a href="http://tech.firefox.sina.com/" title="科技">科技</a></li>
  13. <li><a href="http://sports.firefox.sina.com/" title="体育">体育</a></li>
  14. <li><a href="http://finance.firefox.sina.com/" title="财经">财经</a></li>
  15. <li><a href="http://auto.firefox.sina.com/" title="汽车">汽车</a></li>
  16. </ul>
  17. <i class="iconfont icon-liebiao" id="menu"></i>
  18. </div>"""
  19. # 构造解析对象
  20. parseHtml = etree.HTML(html)
  21. # 利用解析对象调用xpath匹配
  22. r1 = parseHtml.xpath('//a/@href')
  23. #print(r1)
  24. # 获取 /
  25. r2 = parseHtml.xpath('//a[@id="channel"]/@href')
  26. #print(r2)
  27. # 获取非 /
  28. r3 = parseHtml.xpath('//ul[@id="nav"]//a/@href')
  29. #print(r3)
  30. # 获取所有 a 节点的文本内容
  31. r4 = parseHtml.xpath('//a/text()')
  32. #print(r4)
  33. # 获取 图片、军事 ...
  34. r5 = parseHtml.xpath('//ul[@id="nav"]//a')
  35. for i in r5:
  36. print(i.text)

案例1 :抓取百度贴吧帖子里面所有的图片

  • 目标:抓取指定贴吧所有图片
  • 思路:
    • 获取贴吧主页URL,下一页:找URL规律
    • 获取1页中每个帖子的URL
    • 对每个帖子URL发请求,获取帖子里图片URL
    • 对图片URL发请求,以wb方式写入本地文件
  • 步骤
    1. 获取贴吧主页URL

      • http://tieba.baidu.com/f? + 查询参数
    2. 找到页面中所有帖子的URL
      • src : 完整链接
      • href : 和主URL进行拼接
      • 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

    3. 找每个帖子中图片URL
      • Xpath匹配://img[@class="BDE_Image"]/@src
    4. 代码实现
  1. '''百度贴吧图片抓取'''
  2. import requests
  3. from lxml import etree
  4. class TiebaImageSpider:
  5. def __init__(self):
  6. self.headers = {"User-Agent": "Mozilla/5.0"}
  7. self.baseurl = 'https://tieba.baidu.com'
  8. self.pageurl = 'https://tieba.baidu.com/f?'
  9. # 获取所有帖子URL列表
  10. def get_page_url(self, params):
  11. res = requests.get(self.pageurl, params=params, headers=self.headers)
  12. res.encoding = 'utf-8'
  13. print(res.url)
  14. html = res.text
  15. parse_html = etree.HTML(html)
  16. t_list = parse_html.xpath('//div[contains(@class,"t_con")]/div/div/div/a/@href')
  17. print(t_list)
  18. for t_link in t_list:
  19. t_link = self.baseurl + t_link
  20. self.get_image_url(t_link)
  21. # 获取帖子中图片URL列表
  22. def get_image_url(self, t_link):
  23. res = requests.get(t_link, headers=self.headers)
  24. res.encoding = 'utf-8'
  25. html = res.text
  26. parse_html = etree.HTML(html)
  27. img_list = parse_html.xpath('//img[@class="BDE_Image"]/@src')
  28. for img_link in img_list:
  29. self.write_image(img_link)
  30. # 保存到本地
  31. def write_image(self, img_link):
  32. res = requests.get(img_link, headers=self.headers)
  33. res.encoding = 'utf-8'
  34. html = res.content
  35. filename = img_link[-12:]
  36. with open(filename, 'wb') as f:
  37. f.write(html)
  38. print("%s下载成功" % filename)
  39. # 主函数
  40. def main(self):
  41. name = input("请输入贴吧名字:")
  42. begin = int(input("请输入起始页:"))
  43. end = int(input("请输入中止页:"))
  44. for n in range(begin, end + 1):
  45. pn = (n - 1) * 50
  46. params = {'kw': name,
  47. 'pn': str(pn)}
  48. self.get_page_url(params)
  49. # s = '//div[@class="t_con cleafix"]/div/div/div/a/@href'
  50. # s = '//*[@id="thread_list"]/li/div/div[2]/div[1]/div[1]/a/@href'
  51. # s2 = '//cc/div/img[@class="BDE_Image"]/@src'
  52. if __name__ == '__main__':
  53. spider = TiebaImageSpider()
  54. spider.main()

案例2:糗事百科-xpath

  • 目标 :用户昵称、段子内容、好笑数、评论数
  • 步骤
    • 找URL

      • https://www.qiushibaike.com/8hr/page/1/
    • xpath匹配
      • 基准xpath://li[contains(@id,"qiushi")]

        • 标题内容:``
        • 用户昵称:.//span[@class="recmd-name"]
        • 好笑数量:./div/div/div/span[1]
        • 评论数量:./div/div/div/span[4]
  1. import requests
  2. from lxml import etree
  3. import pymongo
  4. class QiuShiSpider:
  5. def __init__(self):
  6. self.url = "https://www.qiushibaike.com/"
  7. self.headers = {"User-Agent": "Mozilla/5.0"}
  8. self.conn = pymongo.MongoClient("localhost", 27017)
  9. self.db = self.conn.spiderdb
  10. self.set = self.db.qiushi
  11. def get_page(self):
  12. res = requests.get(self.url, headers=self.headers)
  13. res.encoding = 'utf-8'
  14. html = res.text
  15. self.parse_page(html)
  16. def parse_page(self, html):
  17. parse_html = etree.HTML(html)
  18. # 匹配每个段子列表
  19. base_list = parse_html.xpath('//li[contains(@id,"qiushi")]')
  20. # 遍历每个段子的借点对象
  21. for base in base_list:
  22. # 标题
  23. title = base.xpath('./div/a')[0].text
  24. # 用户昵称
  25. username = base.xpath('.//span[@class="recmd-name"]')[0].text
  26. # 好笑数量
  27. try:
  28. laugh_num = base.xpath('./div/div/div/span[1]')[0].text
  29. # 或:laugh_num = base.xpath('./div/div/div/span')[0].text
  30. except IndexError:
  31. laugh_num = 0
  32. # 评论数量
  33. try:
  34. com_num = base.xpath('./div/div/div/span[4]')[0].text
  35. # com_num = base.xpath('./div/div/div/span')[3].text
  36. except IndexError:
  37. com_num = 0
  38. d = {
  39. "title": title,
  40. "username": username,
  41. "laugh_num": laugh_num,
  42. "com_num": com_num
  43. }
  44. self.set.insert(d)
  45. print("存入数据库成功!")
  46. if __name__ == "__main__":
  47. spider = QiuShiSpider()
  48. spider.get_page()

Spider_lxml的更多相关文章

随机推荐

  1. 关于HttpClient模拟浏览器请求的參数乱码问题解决方式

    转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/44407297 http://www.llwjy.com/blogdetail/9 ...

  2. 烦人的Facebook分享授权

    开发端授权app权限 facebook要求提交应用到他们平台, 并且还限制100mb, 坑爹死了, 果断使用google drive分享给他们, 最開始不确定分享给他们什么样的程序包, 结果审核没通过 ...

  3. caioj1441:第k小的数Ⅰ

    [传送门:caioj1441] 简要题意: 给出一个n个数的序列,m个询问,每个询问输入l,r,k,输出第l个数到第r个数第k小的数 题解: 首先想到线段树,但是做不到询问区间的第几小,只能做到最大或 ...

  4. 算法导论————KMP

    [例题传送门:caioj1177] KMP模版:子串是否出现 [题意]有两个字符串SA和SB,SA是母串,SB是子串,问子串SB是否在母串SA中出现过.如果出现过输出第一次出现的起始位置和结束位置,否 ...

  5. 目前常见的三种SQL分页方式:

    --top not in方式 select top 条数 * from tablename where Id not in (select top 条数*页数 Id from tablename) - ...

  6. BZOJ 4430 Guessing Camels

    Description Jaap, Jan, and Thijs are on a trip to the desert after having attended the ACM ICPC Worl ...

  7. Aix下查看内存命令

    1. 查看物理内存配置 # lsdev -Cc memory  查看配置的物理内存设备,下面为其输出示例:  L2cache0 Available L2 Cache   mem0 Available ...

  8. 用vuex构建单页

    原文地址:点我 前言:在最近学习 Vue.js 的时候,看到国外一篇讲述了如何使用 Vue.js 和 Vuex 来构建一个简单笔记的单页应用的文章.感觉收获挺多,自己在它的例子的基础上进行了一些优化和 ...

  9. AI:OPENCV实现人脸的自动识别

    依赖jar包: faceRecognition.java package opencv; import java.awt.Graphics; import java.awt.image.Buffere ...

  10. CSUOJ 1651 Weirdo

    1651: Weirdo Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 40  Solved: 21[Submit][Status][Web Board ...