爬虫 --- 02. 爬取图片,数据解析

一.两种爬取图片的方法

  ①requests方法

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

img_url = 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1559019106959&di=3aa954df95d2e55083d85de8391118c5&imgtype=0&src=http%3A%2F%2Fimg3.duitang.com%2Fuploads%2Fitem%2F201601%2F28%2F20160128195606_xvawC.jpeg'

img_data = requests.get(url=img_url,headers=headers).content

with open('./meinv.jpg','wb') as fp:
    fp.write(img_data)

 

  ②request方法

from urllib import request
img_url
= 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1559019106959&di=3aa954df95d2e55083d85de8391118c5&imgtype=0&src=http%3A%2F%2Fimg3.duitang.com%2Fuploads%2Fitem%2F201601%2F28%2F20160128195606_xvawC.jpeg'
request.urlretrieve(img_url,
'./meishaonv.jpg') #图片,压缩包,视频等一定要加好后缀

 

二.数据解析

  1.正则

  单字符:
        . : 除换行以外所有字符
        [] :[aoe] [a-w] 匹配集合中任意一个字符
        \d :数字  [0-9]
        \D : 非数字
        \w :数字、字母、下划线、中文
        \W : 非\w
        \s :所有的空白字符包,括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
        \S : 非空白
    数量修饰:
        * : 任意多次  >=0
        + : 至少1次   >=1
        ? : 可有可无  0次或者1次
        {m} :固定m次 hello{3,}
        {m,} :至少m次
        {m,n} :m-n次
    边界:
        $ : 以某某结尾 
        ^ : 以某某开头
    分组:
        (ab)  
    贪婪模式: .*
    非贪婪(惰性)模式: .*?

    re.I : 忽略大小写
    re.M :多行匹配
    re.S :单行匹配

    re.sub(正则表达式, 替换内容, 字符串)

 

正则解析
  需求:爬取糗事百科中所有的糗图图片数据
  实现:
    检查页面中的图片数据是否为动态加载的
    将当前页面的源码数据请求到
    使用正则表达式定位相关的img标签,然后获取img的src属性值
    对src的属性值发起请求获取图片数据
    持久化存储图片数据

 

import requests
import re
import os
from urllib import request
if not os.path.exists('./qiutu'): os.mkdir('./qiutu')
headers
= { 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36' } url = 'https://www.qiushibaike.com/pic/'

page_text = requests.get(url=url,headers=headers).text ex = '<div class="thumb">.*?<img src="(.*?)" alt.*?</div>' img_url = re.findall(ex,page_text,re.S) for url in img_url: url = 'https:'+url img_name = url.split('/')[-1] img_path = './qiutu/'+img_name request.urlretrieve(url,img_path) print(img_name,'下载成功!!!')

 

  2. bs4解析

  ①环境安装

输入

  pip3 install bs4   pip3 install lxml

 

   ②原理

解析原理:
  实例化一个Beautifulsoup的对象,且将页面源码数据加载到该对象中
  使用该对象的相关属性和方法实现标签定位和数据提取
实例化Beautifulsoup对象
  BeautifulSoup(page_text,'lxml'):将从互联网上请求到的页面源码数据加载到该对象中
  BeautifulSoup(fp,'lxml'):将本地存储的一样页面源码数据加载到该对象中

soup = BeautifulSoup(fp,'lxml')   #示例化

 

 

   ③定位

#①soup.tagName:只可以定位到第一次出现的tagName标签
  soup.title
  soup.div

 

#soup.find(‘tagName’)
soup.find('a')  # soup.a
#②属性定位
soup.find('div',class_='song')

 

#③find_all
soup.find_all('div')[2]

 

#④select('选择器')
soup.select('.song')

  ‘>’:表示一个层级

  soup.select('.tang > ul > li > a')

 

  空格:表示多个层级

  soup.select('.tang a')

 

   ④取值

#取文本:string取的是直系的文本数据,text获取的是全部的数据
soup.p.string

 #取后代中的所有文本数据

 soup.find('div',class_='tang').get_text()
  soup.find('div',class_='tang').text

 

 

#取属性
soup.a['href']

 

   ⑤示例

爬取古诗文网的三国演义小说(过程):
  页面数据是否为动态加载   在首页中解析章节标题和标题对应的详情页的url   对详情页url发起请求获取详情页的源码数据   检查详情页是否存在动态加载的数据   解析详情页中的章节内容   持久化存储
import requests
from bs4 import BeautifulSoup

url = 'http://www.shicimingju.com/book/sanguoyanyi.html' page_text = requests.get(url=url,headers=headers).text #数据解析:标题和url soup = BeautifulSoup(page_text,'lxml') li_list = soup.select('.book-mulu > ul > li') fp = open('./sanguo.txt','w',encoding='utf-8') for li in li_list: title = li.a.string detail_url = 'http://www.shicimingju.com'+li.a['href'] # print(title,detail_url) #单独对详情页发起请求获取源码数据 detail_page_text = requests.get(url=detail_url,headers=headers).text soup = BeautifulSoup(detail_page_text,'lxml') content = soup.find('div',class_="chapter_content").text fp.write(title+'\n'+content+'\n') print(title,':下载成功!') fp.close()

 

 

   3. xpath解析

  ①环境安装

pip install lxml

- 解析效率比较高
- 通用性最强的

 

  ②工作原理

 

- 解析原理:
    - 实例化一个etree对象且将即将被解析的页面源码数据加载到该对象中
    - 使用etree对象中的xpath方法结合着xpath表达式进行标签定位和数据提取
- 实例化etree对象
    - etree.parse('本地文件路径')
    - etree.HTML(page_text)

from lxml import etree
tree = etree.parse('./test.html')    #实例化对象

 

 

 

 

   ③定位

#①定位title标签
tree.xpath('/html/head/title')
tree.xpath('/html//title')
tree.xpath('//title')    #推荐

 

#②定位class=song的div
tree.xpath('//div[@class="song"]')
tree.xpath('//div[2]')  #xpath表达式中的索引是从1开始

 tree.xpath('//div[@class="tang"]/ul/li[4]/a')
  tree.xpath('//div[@class="tang"]//li[4]/a')

 

   ④取值

#取文本(获取李清照) /text()  //text()
tree.xpath('//div[@class="song"]/p[1]/text()')[0]
tree.xpath('//div[@class="song"]/text()')

 

#取属性
tree.xpath('//a/@title')

 

  ⑤示例1

#爬取boss直聘爬虫岗位的信息
from lxml import etree

import requests

url = 'https://www.zhipin.com/job_detail/?query=python%E7%88%AC%E8%99%AB&city=101010100&industry=&position='
page_text = requests.get(url=url,headers=headers).text

#数据解析(jobTitle,salary,company)
tree = etree.HTML(page_text)
li_list = tree.xpath('//div[@class="job-list"]/ul/li')
for li in li_list:
    title = li.xpath('.//div[@class="job-title"]/text()')[0]
    salary = li.xpath('.//span[@class="red"]/text()')[0]
    company = li.xpath('.//div[@class="company-text"]/h3/a/text()')[0]
    print(title,salary,company)

 

  ⑥示例2(管道符的使用)

#爬取全国城市名称
import requests
from lxml import etree

url = 'https://www.aqistudy.cn/historydata/'
page_text = requests.get(url=url,headers=headers).text

tree = etree.HTML(page_text)
# hot_city = tree.xpath('//div[@class="bottom"]/ul/li/a/text()')
# all_city = tree.xpath('//div[@class="bottom"]/ul/div[2]/li/a/text()')
# all_city

tree.xpath('//div[@class="bottom"]/ul/div[2]/li/a/text() | //div[@class="bottom"]/ul/li/a/text()')

 

  ⑦示例3(解决中文乱码问题)

#爬取4k图片带标题

import requests
from lxml import etree start_page = int(input('start page num:')) end_page = int(input('end page num:')) if not os.path.exists('./meinvs'): os.mkdir('./meinvs') #通用的url模板(不能修改) url = 'http://pic.netbian.com/4kmeinv/index_%d.html' for page in range(start_page,end_page+1): if page == 1:                   new_url = 'http://pic.netbian.com/4kmeinv/' else:          #除第一页外,其他url一致 new_url = format(url%page) response = requests.get(url=new_url,headers=headers) # response.encoding = 'utf-8'    #第一种 page_text = response.text #解析名称和图片的src属性值 tree = etree.HTML(page_text) li_list = tree.xpath('//div[@class="slist"]/ul/li') for li in li_list: img_name = li.xpath('./a/img/@alt')[0] img_name = img_name.encode('iso-8859-1').decode('gbk')+'.jpg'  #第二种   img_src = 'http://pic.netbian.com'+li.xpath('./a/img/@src')[0] img_path = './meinvs/'+img_name request.urlretrieve(img_src,img_path) print(img_name,'下载成功!!!')

 

posted @ 2019-05-28 20:08  TNTsc  阅读(1079)  评论(0编辑  收藏  举报