爬虫之数据解析

数据解析可以为我们实现聚焦爬虫

  • 正则
  • bs4
  • xpath
  • pyquery

聚焦爬虫要获取的数据都被存储在了相关标签的属性中

  • 定位标签
  • 获取文本或者属性

爬取一张图片

import requests

headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'
}

url = 'https://c-ssl.duitang.com/uploads/item/201502/22/20150222193803_yhrNV.jpeg'

img_data = requests.get(url,headers=headers).content # bytes类型数据

with open('./img.jpg','wb') as fp:
    fp.write(img_data)
一个自带写入文件功能的模块
# 不能使用ua认证
# Python内置的一个基于请求响应的功能
from urllib import request

url = 'https://c-ssl.duitang.com/uploads/item/201502/22/20150222193803_yhrNV.jpeg'
request.urlretrieve(url,filename='./a.jpg') # 自带写入文件的功能

 

正则

#糗图爬取1-3页所有的图片
#1.使用通用爬虫将前3页对应的页面源码数据进行爬取
#通用的url模板(不可变)
import os
import sys

import re
import requests

from urllib import request

page_count = input('爬取页数: ')

DirName = './ImgFile'
if not os.path.exists(DirName):
    os.mkdir(DirName)

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.122 Safari/537.36'
}

for page in range(1, int(page_count)+1):
    url = f'https://www.qiushibaike.com/imgrank/page/{page}/'
    
    page_text = requests.get(url=url,headers=headers).text # 页码对应的源码数据

    # 使用正则实现聚焦爬虫
    ex = '<div class="thumb">.*?<img src="(.*?)" alt.*?</div>'
    img_src_list = re.findall(ex, page_text, re.S)

    count = 0

    for src in img_src_list:
        
        img_url = 'https:' + src # 图片完整网址
        img_name = os.path.basename(img_url) # 获取图片名
        img_path = os.path.join(DirName,img_name) # 拼接图片保存路径
        
        request.urlretrieve(img_url, img_path) # 一步到位保存文件

        count += 1
        print_str = f"正在抓取第{page}页第{count}条数据"
        print(print_str)

print('数据抓取完毕')
正则爬取嗅事百科图片示例

 

bs4解析

  • 实例化一个BeautifulSoup对象,需要将即将被解析的页面源码数据加载到该对象中
  • 调用BeautifulSoup对象中的相关方法和属性进行标签定位和数据提取
# bs4的安装
pip install bs4
pip install lxml

BeautifulSoup的实例化

  • BeautifulSoup(fp,'lxml'):将本地存储的一个html文档中的数据加载到实例化好的BeautifulSoup对象中
  • BeautifulSoup(page_text,'lxml'):将从互联网上获取的页面源码数据加载到实例化好的BeautifulSoup对象中

定位标签的操作

  • soup.tagName: 定位到第一个出现的tagName标签
  • 属性定位: soup.find('tagName',attrName='value')
  • 属性定位: soup.find_all('tagName',attrName='value'),返回值为列表
  • 选择器定位: soup.select('选择器')
    • 层级选择器: >表示一个层级 空格表示多个层级

获取文本

  • .string:获取直系的文本内容
  • .text:获取所有的文本内容

获取属性

  • tagName'attrName'
from bs4 import BeautifulSoup

fp = open('./test.html','r',encoding='utf-8')

# 将本地存储的一个html文档中的数据加载到实例化好的BeautifulSoup对象中
soup = BeautifulSoup(fp, 'lxml') # html源码

# 获取第一个出现的div标签
a = soup.div
a = soup.find('div')

# 属性定位 
a = soup.find('div', class_='song') 
a = soup.find('a', id='feng')

# 匹配所有符合要求的
a = soup.find_all('div')
a = soup.find_all('div', class_='song')
a = soup.find_all('a', class_='du')

# 选择器定位 获取到的是一个list列表
a = soup.select('#feng')[0]

# 层级选择器
a = soup.select('.tang > ul > li') # > 号表示一个层级
a = soup.select('.tang li') # 空格表示多个层级

# 获取当前层级中所有的文本
a_tag = soup.select('#feng')[0]
a = a_tag.text 

# 获取当前层级中直系的文本
a_tag = soup.find('div',class_='tang')
a = a_tag.string # None

# 获取标签属性
a_tag = soup.select('#feng')[0]
a = a_tag['href']

print(a)

bs4示例爬虫

# http://www.shicimingju.com/book/

# 爬取古籍

# 例: 三国志 
import requests
from bs4 import BeautifulSoup

url = 'http://www.shicimingju.com'
poetry_url = 'http://www.shicimingju.com/book/sanguozhi.html'

file = open('三国志.txt','a',encoding='utf-8')

headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'
}

page_text = requests.get(url=poetry_url,headers=headers).text

soup = BeautifulSoup(page_text,'lxml')

page_list = soup.select('.book-mulu > ul > li > a')

for page in page_list:

    page_name = page.string
    page_url = url + page['href']

    book_text = requests.get(url=page_url, headers=headers).text
    book_soup = BeautifulSoup(book_text, 'lxml')
    book_txt = book_soup.find('div', class_='chapter_content').text
    txt = page_name + '\n' + book_txt + '\n'
    file.write(txt)
    print(f'章节{page_name}下载完毕')

file.close()
bs4爬取诗词名句

 

xpath解析

  • 实例化一个etree的对象,然后将即将被解析的页面源码加载到改对象中
  • 使用etree对象中的xpath方法结合着不同形式的xpath表达式实现标签定位和数据提取
安装: pip install lxml

etree对象的实例化

etree.parse('test.html') 加载本地的html

etree.HTML(page_text)

xpath表达式:xpath方法的返回值一定是一个列表

  • 最左侧的/表示:xpath表达式一定要从根标签逐层进行标签查找和定位
  • 最左侧的//表示:xpath表达式可以从任意位置定位标签
  • 非最左侧的/:表示一个层级
  • 非最左侧的//:表示夸多个层级
  • 属性定位://tagName@attrName="value"
  • 索引定位://tagNameindex 索引是从1开始

取文本:

  • /text():直系文本内容
  • //text():所有的文本内

取属性:

  • /@attrName
from lxml import etree

# 加载本地html
tree = etree.parse('./test.html')

# xpath返回的是一个列表

# 绝对路径匹配 逐层标签查找
a = tree.xpath('/html/head/title')
a = tree.xpath('/html/body/div/p')

# 相对路径 从任意位置定位标签
a = tree.xpath('//p')

# //表示多个层级
a = tree.xpath('//div//li')

# 属性查找
a = tree.xpath("//div[@class='song']")

# 索引定位,定位第七个li标签,索引从1开始计数
a = tree.xpath('//li[7]')

# 获取文本

# 获取直系文本
a = tree.xpath("//a[@class='du']/text()")[0]

# 获取所有文本
a = tree.xpath("//div[@class='song']//text()")

# 获取属性
a = tree.xpath("//a[@id='feng']/@href")

print(a)

 

xpath示例代码

from lxml import etree

import requests

init_url = 'https://www.qiushibaike.com'
url = 'https://www.qiushibaike.com/text/'

headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'
}

html_text = requests.get(url=url, headers=headers).text

tree = etree.HTML(html_text)

html_list = tree.xpath("//a[@class='contentHerf']/@href")

for html in html_list:
    new_url = init_url + html

    # 实现局部解析
    new_text = requests.get(url=new_url, headers=headers).text

    txt_tree = etree.HTML(new_text)

    content = txt_tree.xpath("//div/div[@class='content']//text()")
    content = ''.join(content)
    
    print(content)
xpath爬取糗事百科段子
# http://pic.netbian.com/4kdongman/index.html

import os
import sys

import requests
from urllib import request
from lxml import etree

ImgFile = '4K动漫壁纸'

headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'
}

url = f'http://pic.netbian.com/4kdongman/index_%d.html'
img_in_url = 'http://pic.netbian.com'

if not os.path.exists(ImgFile):
    os.mkdir(ImgFile)

for page in range(1,11):
    if page == 1:
        new_url = 'http://pic.netbian.com/4kdongman/index.html'
    else:
        new_url = url%page
    
    int_htm = requests.get(url=new_url,headers=headers).text

    ini_obj = etree.HTML(int_htm)
    img_hm_lis = ini_obj.xpath("//div[@class='slist']//li/a/@href")

    for hml in img_hm_lis:
        img_src = img_in_url + hml

        img_url = requests.get(url=img_src,headers=headers).text

        img = etree.HTML(img_url)
        img = img.xpath("//a[@id='img']/img/@src")[0]
        ImgName = os.path.basename(img)
        ImgPath = os.path.join(ImgFile, ImgName)
        ImgUrl = img_in_url+img
        request.urlretrieve(ImgUrl, filename=ImgPath)
        print(ImgName,'下载完成')
xpath爬取彼岸图网壁纸

# 获取所有城市名
https://www.aqistudy.cn/historydata/
提升

 

posted @ 2020-04-29 20:28  CatdeXin  阅读(183)  评论(0)    收藏  举报