第三章:数据解析

爬取页面的内容

编码流程:

  • 指定url
    • 发起请求
    • 获取响应数据
    • 数据解析
    • 持久化存储

数据解析的分类:

  • 正则(了解)
  • bs4(了解)
  • xpath(重点)

数据解析的原理:

解析的局部的文本内容都会在标签之间或者标签对应的属性中进行存储

  1. 进行指定标签的定位
  2. 标签或者标签对应的属性中存储的数据值进行提取(解析)

0.图片的爬取:

  1. import requests
  2. if __name__ == '__main__':
  3. # content 返回一个二进制形式的数据
  4. # text (文本) content (二进制) json() (对象)
  5. url = 'https://pic1.zhimg.com/v2-a95e9350681a5bc4f1d79988deff2a5c_b.jpg'
  6. img_data = requests.get(url=url).content
  7. with open('test.gif', 'wb') as fp:
  8. fp.write(img_data)

1.正则解析

html

  1. <div class="thumb">
  2. <a href="/article/123657832" target="_blank">
  3. <img src="//pic.qiushibaike.com/system/pictures/12365/123657832/medium/BYTTLNQ3HW0ST63W.jpg" alt="糗事#123657832" class="illustration" width="100%" height="auto">
  4. </a>
  5. </div>

正则

  1. ex = '<div class="thumb">.*?<img src="(.*?)" alt=.*?</div>'

代码

  1. import requests
  2. import re
  3. import os
  4. from tqdm import tqdm
  5. if __name__ == '__main__':
  6. if not os.path.exists('./img'):
  7. os.mkdir('./img')
  8. # UA伪装
  9. headers = {
  10. 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36 Edg/87.0.664.52'
  11. }
  12. url = 'https://www.qiushibaike.com/imgrank/'
  13. html = requests.get(url=url, headers=headers).text
  14. # 使用聚焦爬虫将页面中所有的糗图进行解析/提取
  15. ex = '<div class="thumb">.*?<img src="(.*?)" alt.*?</div>'
  16. img_src_list = re.findall(ex, html, re.S)
  17. for src in tqdm(img_src_list):
  18. src = 'https:'+src
  19. image_data = requests.get(url=src).content
  20. image_name = src.split('/')[-1]
  21. with open('./img/' + image_name, 'wb') as fp:
  22. fp.write(image_data)

注意:

1.获取图片的名称

  1. image_name = src.split('/')[-1]

2.正则解析-分页下载

  1. import requests
  2. import re
  3. import os
  4. from tqdm import tqdm
  5. if __name__ == '__main__':
  6. if not os.path.exists('./img'):
  7. os.mkdir('./img')
  8. # UA伪装
  9. headers = {
  10. 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36 Edg/87.0.664.52'
  11. }
  12. for page in range(1, 13):
  13. print("下载第%d页的图片" % page)
  14. url = 'https://www.qiushibaike.com/imgrank/page/' + str(page)
  15. html = requests.get(url=url, headers=headers).text
  16. # 使用聚焦爬虫将页面中所有的糗图进行解析/提取
  17. ex = '<div class="thumb">.*?<img src="(.*?)" alt.*?</div>'
  18. img_src_list = re.findall(ex, html, re.S)
  19. for src in tqdm(img_src_list):
  20. src = 'https:' + src
  21. image_data = requests.get(url=src).content
  22. image_name = src.split('/')[-1]
  23. with open('./img/' + image_name, 'wb') as fp:
  24. fp.write(image_data)

3.xpath 解析方式(首选)

xpath的解析原理

  • 实例化一个etree的对象,且需要将需解析的数据源码加载到改对象中
  • 调用etree对象中的xpath方法结合着xpath表达式实现标签的定位和内容的捕获

环境安装

  • pip install lxml

如何实例化etree对象 from lxml import etree

  • 将本地的html文档中的源码数据加载到etree对象中
    • etree.parse(filePath)
  • 将互联网上获取的源码数据加载到该对象中
    • etree.HTML(‘page_text’)
  • xpath(‘xpath表达式’)

3.xpath表达式:

  1. /:表示的是从根节点开始定位。表示的是一个层级。
  2. //:表示的是多个层级。可以表示从任意位置开始定位。
  3. 属性定位://[@class=’song’] tag[@attrName=”attrValue”]
  4. 索引定位://div[@class=”song”]/p[3] 索引是从1开始的。
  5. 取文本:
    • /text() 获取的是标签中直系的文本内容
    • //text() 标签中非直系的文本内容(所有的文本内容)
  6. 取属性:
    1. /@attrName ==>img/src

6.xpath解析案例-58二手房

  1. import requests
  2. from lxml import etree
  3. if __name__ == '__main__':
  4. headers = {
  5. 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36 Edg/87.0.664.52'
  6. }
  7. url = 'https://yz.58.com/ershoufang/'
  8. html = requests.get(url=url, headers=headers).text
  9. tree = etree.HTML(html)
  10. li_list = tree.xpath('//ul[@class="house-list-wrap"]/li')
  11. with open('./58.txt', 'w', encoding='utf-8') as pf:
  12. for li in li_list:
  13. title = li.xpath('./div[2]/h2/a/text()')[0]
  14. print(title)
  15. pf.write(title + '\n')

7.xpath解析案例-4k图片解析爬取

  1. import requests
  2. import os
  3. from lxml import etree
  4. from tqdm import tqdm
  5. if __name__ == '__main__':
  6. headers = {
  7. 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36 Edg/87.0.664.52'
  8. }
  9. url = 'http://pic.netbian.com/4kmeinv/index_7.html'
  10. html = requests.get(url=url, headers=headers).text
  11. tree = etree.HTML(html)
  12. li_list = tree.xpath('//div[@class="slist"]/ul/li')
  13. if not os.path.exists('./美女图片'):
  14. os.mkdir('./美女图片')
  15. for li in tqdm(li_list):
  16. # 拼接图片地址
  17. img_src = "http://pic.netbian.com" + li.xpath('./a/img/@src')[0]
  18. # 得到图片后缀
  19. img_suffix = '.'+str(img_src.split('.')[-1])
  20. # 拼接图片名称
  21. img_name = li.xpath('./a/img/@alt')[0] + img_suffix
  22. # 通用处理中文乱码的解决方案
  23. img_name = img_name.encode('iso-8859-1').decode('gbk')
  24. # 下载图片
  25. img_data = requests.get(url=img_src, headers=headers).content
  26. # 持久化
  27. with open('./美女图片/'+img_name, 'wb') as fp:
  28. fp.write(img_data)

解决数据编码格式

  1. # 手动设定响应数据的编码格式
  2. response.encoding = 'utf-8'
  3. # 通用处理中文乱码的解决方案
  4. img_name = img_name.encode('iso-8859-1').decode('gbk')

7.xpath解析案例-4k图片解析爬取-升级

  1. import requests
  2. import os
  3. from lxml import etree
  4. from tqdm import tqdm
  5. if __name__ == '__main__':
  6. headers = {
  7. 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36 Edg/87.0.664.52'
  8. }
  9. for page in range(2, 8):
  10. url = 'http://pic.netbian.com/4kmeinv/index_%s.html' % page
  11. html = requests.get(url=url, headers=headers).text
  12. tree = etree.HTML(html)
  13. li_list = tree.xpath('//div[@class="slist"]/ul/li')
  14. if not os.path.exists('./美女图片'):
  15. os.mkdir('./美女图片')
  16. for li in tqdm(li_list):
  17. # 去详情页爬取
  18. href = li.xpath('./a/@href')[0]
  19. detail_url = 'http://pic.netbian.com' + href
  20. detail_html = requests.get(url=detail_url, headers=headers).text
  21. detail_tree = etree.HTML(detail_html)
  22. detail_img_url = 'http://pic.netbian.com' + detail_tree.xpath('//*[@id="img"]/img/@src')[0]
  23. # 得到图片后缀
  24. img_suffix = '.' + detail_img_url.split('.')[-1]
  25. # 拼接图片名称
  26. img_name = detail_tree.xpath('//h1/text()')[0] + img_suffix
  27. # 通用处理中文乱码的解决方案
  28. img_name = img_name.encode('iso-8859-1').decode('gbk')
  29. # 下载图片
  30. img_data = requests.get(url=detail_img_url, headers=headers).content
  31. # 持久化
  32. with open('./美女图片/' + img_name, 'wb') as fp:
  33. fp.write(img_data)

7.xpath解析案例-4k图片解析爬取-终极版

其实上面的图片都不够清晰,根本不是什么4K

通过我的研究,找到下载4k图片的方法:
1607169233909.png

但是我get最后一个链接,图片直接从浏览器上面下载下来了,但我不知道如何在python中处理????

  1. http://pic.netbian.com/4kmeinv/index_2.html
  2. http://pic.netbian.com/tupian/11136.html
  3. http://pic.netbian.com/e/extend/downpic.php?id=11136
  4. {"msg": 4,"pic":"/downpic.php?id=11136&classid=54"}
  5. http://pic.netbian.com/downpic.php?id=11136&classid=54
  6. http://pic.netbian.com/e/extend/downpic.php?id=26596

8.xpath解析案例-全国城市名称爬取

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. import requests
  4. from lxml import etree
  5. #项目需求:解析出所有城市名称https://www.aqistudy.cn/historydata/
  6. if __name__ == "__main__":
  7. # headers = {
  8. # 'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
  9. # }
  10. # url = 'https://www.aqistudy.cn/historydata/'
  11. # page_text = requests.get(url=url,headers=headers).text
  12. #
  13. # tree = etree.HTML(page_text)
  14. # host_li_list = tree.xpath('//div[@class="bottom"]/ul/li')
  15. # all_city_names = []
  16. # #解析到了热门城市的城市名称
  17. # for li in host_li_list:
  18. # hot_city_name = li.xpath('./a/text()')[0]
  19. # all_city_names.append(hot_city_name)
  20. #
  21. # #解析的是全部城市的名称
  22. # city_names_list = tree.xpath('//div[@class="bottom"]/ul/div[2]/li')
  23. # for li in city_names_list:
  24. # city_name = li.xpath('./a/text()')[0]
  25. # all_city_names.append(city_name)
  26. #
  27. # print(all_city_names,len(all_city_names))
  28. headers = {
  29. 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
  30. }
  31. url = 'https://www.aqistudy.cn/historydata/'
  32. page_text = requests.get(url=url, headers=headers).text
  33. tree = etree.HTML(page_text)
  34. #解析到热门城市和所有城市对应的a标签
  35. # //div[@class="bottom"]/ul/li/ 热门城市a标签的层级关系
  36. # //div[@class="bottom"]/ul/div[2]/li/a 全部城市a标签的层级关系
  37. a_list = tree.xpath('//div[@class="bottom"]/ul/li/a | //div[@class="bottom"]/ul/div[2]/li/a')
  38. all_city_names = []
  39. for a in a_list:
  40. city_name = a.xpath('./text()')[0]
  41. all_city_names.append(city_name)
  42. print(all_city_names,len(all_city_names))

4.bs4

使用流程:

  • 实例化一个beautifulSoup对象,并将页面加载到其中
  • 通过beautifulSoup对象中的属性和方法进行标签定位和数据提取

环境安装

  • pip install bs4
  • pip install lxml

如何使用

  1. 导包 from bs4 import BeautifulSoup
  2. 实例化BeautifulSoup

    • 引入本地的文件

      1. fp = open('./test.html', 'w', encoding='utf-8')
      2. soup = BeautifulSoup(fp, 'lxml')
    • 引入网络资源

      1. page_text = response.text
      2. soup = BeautifulSoup(page_text, 'lxml')

BeautifulSoup相关方法

获取相关标签:

  1. soup.tagName 返回HTML中第一出现的tagName的标签
  2. soup.find('tagName') 返回HTML中第一出现的tagName的标签
  3. soup.find('tagName',class_/id/attr='song')
  4. soup.find_all() 参数通find() 返回HTML中全部出现的tagName的标签
  5. soup.select('') 可以使用选择器 类选择器,标签选择器,块选择器 返回列表
  6. soup.select('.tang>ul>li>a')> 表示一个层级
  7. soup.select('.tang>ul>li>a') 空格表示多个层级

获取标签之间的文本值:

  1. souop.a.text/string/get_text()
  2. text/get_text()可以获取标签中所有的文本内容
  3. string只可以获取直系的文本内容

获取标签中属性值:

  1. soup.a['herf']

作业:

爬取站长素材中免费简历模板