首先,值得庆幸的是,代码能完美运行了。但是我这个人不喜欢太开心的事情,有点强迫症(追求完美)。所以我没那么太开心,加上这个项目搞得我很烦,因为这个项目算是我零基础学习python加上我四年没碰过代码的生疏感,前前后后花了将近2个月的时间,累计实际学习时间不会超过10天,这中间肯定学学玩玩,到后面直接不想学了。
那么先说下这个项目,对于我来说是人生当中自己写的第一个项目。我来评价他的话就是,好比写作业,3小时能写完,但是别人只花10分钟写完了,效率不高。
废话不多说了,下面是代码
# time:2019.9.13
# author:小白之神111
# project:爬网页图片
import os
import time
import requests
import re
import random
from lxml import etree
# allow_redirects=False表示禁止重定向,这个东西在下面的代码中
# 如果有requests.get()的地方都加上了,如果要修改,就在这里面修改
# 然后重定向状态码:
# 301 redirect: 301 代表永久性转移(Permanently Moved)
# 302 redirect: 302 代表暂时性转移(Temporarily Moved)
shouye = "https://www.mm131.net"
dic = {"0": "/xinggan/", "1": "/qingchun/", "2": "/xiaohua/", "3": "/chemo/", "4": "/qipao/",
"5": "/mingxing/"} # 菜单栏 有6个
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",
"Referer": "https://www.mm131.net/"}
# 伪造浏览器访问
url_list = []
for i in range(6):
url_list.append(shouye + dic[str(i)]) # 拿到网址
print("\n".join(url_list))
##url_list=[]的内容就是:
##https://www.mm131.net/xinggan/
##https://www.mm131.net/qingchun/
##https://www.mm131.net/xiaohua/
##https://www.mm131.net/chemo/
##https://www.mm131.net/qipao/
##https://www.mm131.net/mingxing/
os.chdir(os.getcwd())
if not os.path.exists(os.getcwd() + "/picture"):
print("目录不存在,准备创建目录")
os.mkdir("picture")
os.chdir(os.getcwd() + "/picture")
else:
print("目录已存在")
os.chdir(os.getcwd() + "/picture")
# time.sleep(5)
localpath = os.getcwd() # 原始目录
print("\n原始地址是:" + str(localpath))
# time.sleep(20)
# 进行分栏的切换
# ==========================第1层==========================
for j in range(len(url_list)):
url = url_list[j] # 每个分栏的地址www.xxxx/xxx/.com
## url的内容就是:
## https://www.mm131.net/xinggan/
# print("\n"+url+"\n")
res = requests.get(url=url, headers=headers, allow_redirects=False) # 解析每个网址www.xxxx/xxx/.com
# 这个是万能公式,解决网页解析下来乱码的问题
res.encoding = res.apparent_encoding
response = res.text # 解析完成的网页
html = etree.HTML(response) # 格式化网页 总体的大纲
# 准备提取每一栏的页数地址
pages = html.xpath("/html/body/div[@class='main']/dl/dd[@class='page']/a/@href") # 每个分栏里面的页数
last = re.findall(r"\d+", str(pages[-1])) # 每一栏最后的页数
last_page = int(last[-1]) # 每一栏最后的页数
# print("\n".join(pages))
## pages的内容是:
## list_6_2.html
## list_6_3.html
## list_6_4.html
## list_6_5.html
## list_6_6.html
## list_6_7.html
# print("最后的页数是:",last_page)
# 下面开始拼接制作每一页的地址
c = 0
pic_page = re.sub(r"\d+\.", "{}", pages[-1])
# pic_page就是做匹配 内容是:list_6_{}html
picad = [] # 把每页的地址放在这个列表里面
# 找到当前这一栏中所拥有的所有的页数
# ==========================第2层==========================
for ye in range(1, last_page + 1):
if c == 0:
picad.append(url) # picad就是每个套图的地址
c = 1
else:
m = str(ye) + "."
picad.append(url + pic_page.format(str(m)))
# picad就是这个https://www.mm131.net/qingchun/list_1_32.html
# print("\n".join(picad))
for page_eve in picad: # 解析每一页的地址
print("现在的页面地址是:" + page_eve + "\n")
# time.sleep(1)
# 解析流程走一下
res_page = requests.get(url=page_eve, headers=headers, allow_redirects=False) # 解析每个网址www.xxxx/xxx/.com
res_page.encoding = res_page.apparent_encoding
response_page = res_page.text # 解析完成的网页
html_page = etree.HTML(response_page)
# 开始收集素材了
allxpath = html_page.xpath("/html/body/div[4]") # 每个界面的最大的div
# 定位到这一页的所有套图,相当于锁定每一个套图
# ==========================第3层==========================
for div in allxpath:
# 这边留个bug,就是我没有获取每一页的最后一页
# 也就是说,当我把一个分栏的图片全部采集完之后他会不会自动跳转
# 到下一栏,这是个问题,留一下这个bug,等下做下测试
# 获取每一个套图的图片地址
# pic=div.xpath("./dl/dd/a/img/@src")
# 这个是我需要的每个套图的总地址,要通过这个地址获取每张图的地址
# 结果是这样的:https://www.mm131.net/xinggan/5044.html
pic_url = div.xpath("./dl/dd/a[@target='_blank']/@href")
# print("\n".join(pic))
## print("\n下面是这页的所有套图地址,正在加载:")
## time.sleep(2)
## print("\n"+"\n".join(pic_url))
## time.sleep(1)
## print("这页一共有:"+str(len(pic_url))+"套图"+"\n\n")#每一页套图的数量(除了最后一页都是20套)
## time.sleep(2)
## print("图片地址:"+"\n".join(pic))
## time.sleep(7)
for x in pic_url:
print("当前套图地址是:" + x)
# x就是这样的:https://www.mm131.net/xinggan/5115.html
# 又是一波解析,这次直接搞图片的地址
res_url = requests.get(url=x, headers=headers, allow_redirects=False)
res_url.encoding = res_url.apparent_encoding
response_url = res_url.text # 解析完成的网页
x_url = etree.HTML(response_url)
# 这次的解析和之前的解析是不一样的界面
y_url = x_url.xpath("/html/body/div[5]/div[4]/span[1]/text()")
# 这边的xpath有几种写法,我现在的写法是直接复制网页里面的xpath
# 问题就在于,如果目标网站做了微小的改动的话,就会报错了,
# 因为获取不到正确的东西,那么就要锁定它本来的面目,下面给出写法
# "/html/body/div[@class='content']/div[@class='contentpage']/span[@class='page-ch']/text()"
# "//span[@class='page-ch'][1]/text()" 这种相比较上一种是简化版,直接找到
# 对应的终极路径,但是上面那种比较稳定,在不出现重复变量的情况下比较好
# 但是速度慢
y_url = str(y_url) # ['共12页']
# print(y_url)
# 找到每套图共有几页
biggests = re.findall(r"\d+", y_url)
biggest = ''.join([str(big) for big in biggests])
# 上面这种比较官方,用于列表内容比较多的情况
# 因为这边就只有一个数字所以也可以用这种写法,如下
# biggest=''.join(str(biggests[-1]))
biggest = int(biggest)
# biggest就是这套图一共有biggest张图片
print("这套图一共有" + str(biggest) + "页\n")
# print(type(biggest))
# 接下来重点,在x这个网页后面加上"xxx_x.html"样式 然后
# 再循环xpath 就可以找到地址了 然后就可以下载
# 只要在这个循环里面做就可以了不用跑到上个循环了
## x: https://www.mm131.net/xinggan/5115.html
## 变成
## change https://www.mm131.net/xinggan/5115_{}.html.foramt(2-最后一张)
number = 0
# 找到每张图片的解析地址
change = re.sub(r"\.h", "_{}.h", x)
# 找到每套图的唯一序号
xuhao = re.findall(r"(\d+).*\/(\d+)\..*", x)
pages_add = xuhao[-1][-1]
# xxxxxxxxxxxxxxxxxxx进行路径切换xxxxxxxxxxxxxxxxxxx
os.chdir(localpath) # 目录重定位,不然会乱
# 给定位,然后判断文件夹在不在,若不在则创建
realpath = os.getcwd() + os.path.sep + str(pages_add)
if not os.path.exists(realpath):
os.mkdir(realpath)
print('\n文件夹' + str(pages_add) + '不存在,创建完成')
else:
print('\n文件夹' + str(pages_add) + '已存在,无需创建')
os.chdir(realpath)
print("\n当前目录是:" + str(os.getcwd()) + "\n")
# xxxxxxxxxxxxxxxxxxx进行路径切换xxxxxxxxxxxxxxxxxxx
# 开始解析每张图片的地址
# ==========================第4层==========================
for kk in range(1, biggest + 1):
if number == 0:
jiexi = x
number = 1
else:
# print(kk)
jiexi = change.format(kk)
# print("当前图片地址是:"+jiexi)
mm_url = requests.get(url=jiexi, headers=headers, allow_redirects=False)
mm_url.encoding = mm_url.apparent_encoding
lookmm_url = mm_url.text # 解析完成的网页
last_url = etree.HTML(lookmm_url)
# print(lookmm_url)
# 进行图片地址解析
fin = last_url.xpath("/html/body/div[5]/div[3]/a/img/@src")
# 这边和上面差不多,给写法//div[@class='content-pic']//@src
# 转换格式,转换成str格式,否则没办法解析
fin_url = ''.join(str(fin[-1]))
# allow_redirects=False禁止重定向
pres = requests.get(url=fin_url, headers=headers, allow_redirects=False)
with open(pages_add + "第" + str(kk) + "张" + ".jpg", "wb") as f:
print("开始下载第" + str(kk) + "张")
f.write(pres.content)
print("结束")
print("由于特殊原因,请等待5秒")
time.sleep(5)
我要说明一下,其中有很多注释是没什么用的,也有很多是我用来验证结果的,也有些事为了方便看懂代码的,所以整体会有点乱。真心要学习的,自己看吧。
还有个重要的事情,我做这个项目路程坎坷,曾经一度想放弃,原因是因为网站的缘故,我一度以为只要找到一个页面进行解析就可以了,没想到后面图片根本出不来,它的页面和图片不在一起,也就是说你能定位到每个套图,但是你没办法只靠这个定位找到图片的地址,所以这个问题烦的我都快疯了。再有我当时想放弃的时候,想着直接定义函数做,因为只要调用就行了,又简洁又快,但是我tm都做了一大半了,同时也是处女作,想想不甘。心,所以硬着头皮搞定它。我在写这个项目的时候也学了很多东西。总之,多写写有好处的。
因为这个版本爬虫速度太慢了也没有使用线程(还没学),考虑到这个,没有在第二层循环再加上文件夹叠加,这种速度也没必要加了。如果跑,一定能把所有的图片全部跑完,没有问题,但是时间上过不去。另外有很多的变量名称没起好,后续会改进,然后后面准备出两个版本,一个是定义函数,一个是在函数的基础上加上线程。最后,本代码只是个人成果,拿出来分享。请勿用于商业违法用途,违者必究!
补充:2020年3月6日17:14:27 这里的代码稍微有点改动,跟之前的一样,也是做了xpath里面的修改。