爬虫学习

目标:爬取壁纸并保存到本地 目标网站:http://desk.zol.com.cn/dongman/


(最后更改时间:2018/11/4)
要求

  • 1.壁纸必须保存到脚本运行目录下的的 IMAGES文件夹内。
  • 2.保存的图片必须以对应标题名和分辨率来命名,如:秋田君的小漫画 – 1920×1200.jpg。
  • 3.图片分辨率应该是可选分辨率中最高的。
  • 4.提示信息格式:正在下载 (下载数量):(图片名字)。
  • 5.要有错误处理并给出相应提示,如:图片下载失败、网络超时的处理等。

要用到的Python库

  • requests(需安装)
  • os
  • lxml中的etree(xpath)(需安装)

相关语法:

  • requests
  • xpath
  • os

准备好这些以后,就可以开始写爬虫了
引入所需库文件

from lxml import etree
import requests
import os

设置头文件

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

写一个解析html的函数,参数为要获取的网址,返回值是解析后的,能用xpath进行定位的xml变量。
步骤:

  • 使用requests中的get方法对网页进行请求,保存在变量r中
  • 将r的编码方式设置为当前编码,防止乱码
  • 使用etree.HTML()解析r.text(),保存在变量dom中
  • 返回dom
def getText(url):
    r = requests.get(url, headers = headers)
    r.encoding = r.apparent_encoding
    dom = etree.HTML(r.text)
    return dom

目标是爬取图片,还需要一个能保存图片的函数:
保存图片与文字不太一样,需要将content(二进制)写入文件而不是text
使用open创建一个文件,因为命名需要使用名字-分辨率的格式来命名,所以我们使用name变量储存名字,px储存分辨率,所以除了将图片的url传入外,还要将这两个参数传进函数
使用f-string方法连接变量和字符串

def getImg(url, name, px):
    r = requests.get(url, headers = headers)
    if(r.status_code != 200):
        print("图片下载失败")
        return
    r.encoding = r.apparent_encoding
    f = open(f'{name}-{px}.jpg', 'wb')
    f.write(r.content)

然后就是文件的保存位置问题,要求是IMAGES文件夹由脚本自动创建,没有就创建,否则不创建。
需要用到os库:

  • 使用os.getcwd()函数得到脚本的工作路径,拼接字符串IMAGES就得到了脚本工作目录下IMAGES文件夹的路径
  • 使用os.path.exists(path)判断文件夹十分存在,不存在则创建
  • 使用os.makedirs(path)创建文件夹
  • 使用os.chdir将工作目录改为IMAGES文件夹下,即使图片保存到该文件夹
def createFileFolder():
    path = os.getcwd() + "IMAGES"
    if not os.path.exists(path):
        os.makedirs(path)
    os.chdir(path)

准备工作完成
我们观察网页结构,发现需要爬取的壁纸共41页,每页的网址规律为:http://desk.zol.com.cn/dongman/x.html
x为页码数
所以写一个循环,次数为41,每次循环爬取当前页上的所有壁纸
firststep:获取图片名和组图链接
  图片名在li标签下,属性值为class=”photo-list-padding”,使用xpath轻松得到图片名,总张数,时间,因为我们目标是爬取每组图片的第一张,所以有用信息只有图片名。组图链接在class=”photo-list-padding”的li标签的href属性中,获取标签中的属性值可以在定位到该标签后使用//@’属性值’得到
secondstep:获取图片最高分辨率对应网址和最高分辨率
  同理可以发现分辨率在dd标签下的a标签的id属性中,而图片链接则在href属性中。
注意:有个严重的问题,从第二页壁纸开始,有一些壁纸不提供下载服务,这些图片的分辨率在网页中找不到,而且也无法获取像其他图片那样获取图片链接,但这类图片在网页中还有个展示的图片,分辨率均为960×600,对应网址都在img标签中的src属性中,分两种情况讨论,程序才不会报错,否则会报错提示分辨率对应的列表为空!
thirdstep:下载图片
  一切都准备好了,写个循环使用getImg()下载图片即可,别忘了打印提示信息


最后附上完整代码

from lxml import etree
import requests
import os

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

def getText(url):
    r = requests.get(url, headers = headers)
    r.encoding = r.apparent_encoding
    dom = etree.HTML(r.text)
    return dom

def getImg(url, name, px):
    r = requests.get(url, headers = headers)
    if (r.status_code != 200):
        print("图片下载失败")
        return
    r.encoding = r.apparent_encoding
    f = open(f'{name}-{px}.jpg', 'wb')
    f.write(r.content)

def createFileFolder():
    path = os.getcwd() + "image"
    if not os.path.exists(path):
        os.makedirs(path)
    os.chdir(path)

def getImgName_href(dom):#得到图片名和图片详细链接
    name = dom.xpath('//li[@class="photo-list-padding"]//em//text()')
    href = dom.xpath('//li[@class="photo-list-padding"]//@href')
    return name, href

def getImgHref_Px(href):#得到最高分辨率图片地址和最高分辨率
    dom = getText(href)
    try:
        px = dom.xpath('//dd[@id="tagfbl"]//a//@id')[0]
        imgUrl = dom.xpath('//dd[@id="tagfbl"]//a[@target="_blank"]//@href')[0]
        dom_1 = getText(host + imgUrl)
        imgHref = dom_1.xpath('//img//@src')[0]
        return imgHref, px
    except:
        imgHref = dom.xpath('//div[@id="mouscroll"]//img//@src')[0]
        return imgHref, "960x600"

host = "http://desk.zol.com.cn"
target = "http://desk.zol.com.cn/dongman/"
cnt = 0
createFileFolder()  # 创建文件夹并将图片下载换到image

for x in range(1, 42):
    dom = getText("http://desk.zol.com.cn/dongman/" + str(x) + ".html")
    name, href = getImgName_href(dom)
    for i in range(0, len(href)):  # 下载壁纸QAQ
        cnt = cnt + 1
        print("正在下载" + str(cnt) + ":" + name[i])
        imgHref, px = getImgHref_Px(host + href[i])
        getImg(imgHref, name[i], px)

文章来源于互联网:Python爬虫学习(一)

发表评论