漫画网站爬虫详解_爬虫怎样爬取网站数据

漫画网站爬虫详解_爬虫怎样爬取网站数据下面对http://www.svmhz.com/shaonvmanhua/进行爬取,对大神的博客进行详解:根据网页图片查看响应代码,选中√的地方查看源代码的方法,浏览器页面按下F12,然后鼠标移动到某个图片时,下面的代码就会变暗如下,选中网页上的图片时,下面的响应代码就会变暗鼠标挪动到图片上就出现了下面

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

下面对
http://www.svmhz.com/shaonvmanhua/进行爬取,对大神的博客(
http://www.jianshu.com/p/8b4a589f7980)进行详解:

根据网页图片查看响应代码,选中√的地方
查看源代码的方法,浏览器页面按下F12,然后鼠标移动到某个图片时,下面的代码就会变暗
漫画网站爬虫详解_爬虫怎样爬取网站数据



如下,选中网页上的图片时,下面的响应代码就会变暗
漫画网站爬虫详解_爬虫怎样爬取网站数据



鼠标挪动到图片上就出现了

下面对爬虫的代码进行逐行解释



—————————— 下面解释get_index_page(offset)函数—————————–
url 

‘http://www.svmhz.com/shaonvmanhua/list_4_%s.html’ 
offset
解释:
漫画网站爬虫详解_爬虫怎样爬取网站数据




漫画网站爬虫详解_爬虫怎样爬取网站数据


以上两张图的3是对应的
该图中的3是对漫画列表提供索引
offset相当于形参,把数据传给s,所以两者前面都有%s
该代码大意比较清楚,如果等待时间比较长,则响应异常,输出相关异常信息
——————————get_index_page(offset)函数————————-
######## 下面解释parser_index_page(html)函数———–
入口参数html代表的是网页源代码

listcon_tag = soup.find(‘ul’, class_=’listcon’)#属性为listcon的列表
漫画网站爬虫详解_爬虫怎样爬取网站数据



列表中的元素<li>……..</li>是每本漫画书的入口
漫画网站爬虫详解_爬虫怎样爬取网站数据




随便打开列表中的一个元素,会发现以下内容
漫画网站爬虫详解_爬虫怎样爬取网站数据



 url_list = listcon_tag.find_all(‘a’, attrs={‘href’: True})
这句话是对网页源代码中  包含的所有漫画书连接 进行提取,得到满足需要的部分网页源代码


 urls = [‘http://www.svmhz.com’ + url[‘href’] for url in url_list]#遍历子网页的子网页,遍历干净为止。
上述代码也就是说,从url_list集合(当前网页的部分源代码)中提取出对链接修饰的部分,拼接到当前网址:
拼接后的结果传给urls集合
该函数的目的是为了获取每本漫画的入口地址,也就是漫画的第一页的地址
函数解释结束
########parser_index_page(html)函数解释结束#########
##############get_image_page(url, total)函数讲解############
total举例(纯数字) :89
list_url = [ ]
解释:
创建一个列表

  list_url.append(url)
在列表中加入每一本漫画入口地址

url = url.split(‘.html’, 2)[0]
把这个url以.html为标记切割2次,切割结果中取第一个

for i in range(2,total+1):
解释:
total+1是取不到的,所以循环的区间是[2,total+1)

urls = url + ‘_’ + str(i) + ‘.html’
ulrs举例:
这个已经是具体到了某特定漫画书的具体某一页了
也就是说该函数的大意是:首先获得每本函数的入口地址,切割改地址后,
后面拼接上页码和html,形成新的地址。
也就是说该函数的目的是:从漫画入口地址=>漫画具体某一页的地址。
新地址存入list_url集合
############get_image_page(url, total)函数讲解结束######

##############parser_image_page(url)讲解#############
该函数的目的是为了获取带有总页数信息
函数的前面部分是为了判断响应是否超时
htmls = etree.HTML(html)

total = htmls.xpath(‘//*[@id=”mh_content”]/div[@class=”dede_pages_all”]/div/ul/li[1]/a/text()’)[0]#右键复制网页源码中的Xpath,然后粘贴
粘贴的办法是:
漫画网站爬虫详解_爬虫怎样爬取网站数据



粘贴结果是://*[@id=”mh_content”]/div[4]/div/ul/li[1]/a
对上述结果进行修改,用 text()函数获取内容
div[4]修改为:
div[@class=”dede_pages_all”]
div[@class=”dede_pages_all”]要作为一个整体来看,也算是特征匹配
dede_pages_all来自下图:
漫画网站爬虫详解_爬虫怎样爬取网站数据



此类路径成为xpath,用于对页面的对象存储的所在路径进行定位。
xpath就是js代码中存储某个标签对应的类对象的路径,根据该路径直达图片的存储网址

最终该函数返回total,也即漫画的总页数





—————–parser_image_page(url)函数讲解结束———————————

———————————get_image_src(url)讲解———————————
该链接是漫画的具体第几页的链接
该函数的作用是向链接发送请求,并且获得响应。

———————————get_image_src(url) 讲解结束—–——————
——————————- 
parser_img_src(html)讲解
——————————-
if语句前出现的变量所代表的对象的具体举例:
titles=【日本漫画】色列本子之[U.R.C] 慧ちゃん限定(13)_少女漫画站
title_page= 【日本漫画】色列本子之[U.R.C] 慧ちゃん限定(13)
title= 【日本漫画】色列本子之[U.R.C] 慧ちゃん限定
if语句后出现的变量的含义如图示
漫画网站爬虫详解_爬虫怎样爬取网站数据



如上图,
漫画网站爬虫详解_爬虫怎样爬取网站数据



img_span 
soup.find
(
‘ul’
{

‘class’

‘mnlt’
}
)
用于在网页源代码中找到图片的存储地址所在的范围

可以看到,上图中有个<img src>接下来进行正则提取,

进一步锁定范围
锁定符合特征的<img src>
img_src 
img_span.find_all
(
‘img’
src
=re.compile
(
‘^http://tu.goldlevi.com/svmhz/uploads2/allimg/[0-9]{1,}/(.*?).jpg$’
))

上面的(。*?)是贪婪匹配


for url in img_src:
    urls = url[‘src’]
    down_image(urls, title, titles)#调用了down_image函数
从url中进一步提取src部分然后赋值给urls,这样urls就得到了图片的存储地址

这里必须一步步搜索范围,否则会把其他不相关的图片包括进来

——————————-
parser_img_src(html)讲解结束
—————————



————————— 
 down_image(url, title, titles)
——————————-
入口参数举例
url = http: // tu.goldlevi.com / svmhz / uploads2 / allimg / 161129 / 2 – 161129102620.jpg
title = 莲子酱绅士福利本 动漫本子邪恶少女漫画
titles = 莲子酱绅士福利本 动漫本子邪恶少女漫画_少女漫画站

调用
save_image函数进行下载,本函数还进行请求,判断请求是否会超时



—————— 
 down_image(url, title, titles)讲解结束
——————————-






————————save_image(content, title, url, titles)讲解—————-
path 

‘D:/pic/’ 

str
(title
)
#确定保存在哪个文件夹下面

if not os.path.exists
(path
)
:
#如果文件夹不存在,就进行保存
    os.mkdir(path)
漫画网站爬虫详解_爬虫怎样爬取网站数据



file_name的开头是结构,后面是path,titles和.jpg,分别替换用彩色线条连接的部分

——————————save_image(content, title, url, titles)结束—————-
#########################结尾###################
if __name__ == ‘__main__’:
    groups = [x for x in range(1, 86)]#爬http://www.svmhz.com/shaonvmanhua/的一部分,总共有85页
    pool = Pool()
    pool.map(main, groups)#
漫画网站爬虫详解_爬虫怎样爬取网站数据



########################结尾讲解结束###################
——————————————————————附上Python3.6源代码——————————————————————————

#-*- coding: utf-8 -*-#-*- coding: utf-8 -*-
from requests.exceptions import RequestException
from bs4 import BeautifulSoup
from multiprocessing import Pool
from lxml import etree
import requests, os, re


def get_index_page(offset):#√
    url = 'http://www.svmhz.com/shaonvmanhua/list_4_%s.html' % offset#offset是形参,用来传给s
    try:
        response = requests.get(url)
        response.encoding = response.apparent_encoding
        if response.status_code == 200:
            return response.text
        print('链接返回出现异常')
        return None
    except RequestException:
        print('爬虫出现异常')
        return None


def parser_index_page(html):#√该函数是为了找到漫画对应的连接在什么地方
    soup = BeautifulSoup(html, 'lxml')
    listcon_tag = soup.find('ul', class_='listcon')#属性为listcon的列表
#在源码中被ui包起来的部分,也就是找到被ul包围起来的列表
    if listcon_tag:
        url_list = listcon_tag.find_all('a', attrs={'href': True})#找到所有的修正部分
        #print("url_list",url_list)
        if url_list:
            urls = ['http://www.svmhz.com' + url['href'] for url in url_list]#遍历子网页的子网页,遍历干净为止。
            return urls#获得各个漫画本的入口的集合,例如http://www.svmhz.com/shaonvmanhua/9642.html


def get_image_page(url, total):#√该函数是为了获取所有子网页的集合
    list_url = []#python的列表创建
    list_url.append(url)
    #print("################")
    #print("url = ",url)
    #print("################")
    #print("total = ",total)
    url = url.split('.html', 2)[0]#把这个url以.html为标记切割2次,切割结果中取第一个
    for i in range(2,total+1):#total+1是取不到的


        urls = url + '_' + str(i) + '.html'#ulrs举例:http://www.svmhz.com/shaonvmanhua/6952_165.html,这个已经是具体到了某特定漫画书的具体某一页了
        list_url.append(urls)
    return list_url#这个函数之所以这么处理,并且序号从2开始,是因为漫画打开后的第一页是没有页码的,页数从每本漫画的第2页才开始


def parser_image_page(url):#获取带有总页数信息的字符串
    try:
        response = requests.get(url)
        response.encoding = response.apparent_encoding
        if response.status_code == 200:
            html = response.text
            htmls = etree.HTML(html)#提取页面数据
            total = htmls.xpath('//*[@id="mh_content"]/div[@class="dede_pages_all"]/div/ul/li[1]/a/text()')[0]#右键复制网页源码中的Xpath,然后粘贴
            if total:
                return total#这里返回的信息举例:“本漫画共69页”
        print('链接异常')
        return None
    except RequestException:
        print('爬虫异常')
        return None


def get_image_src(url):
    #print("此处的url",url)#举例:http://www.svmhz.com/shaonvmanhua/9370_4.html
    try:
        response = requests.get(url)
        print("response",response)
        response.encoding = response.apparent_encoding
        if response.status_code == 200:
            return response.text
        print('链接异常')
        return None
    except RequestException:
        print('爬虫异常')
        return None


def parser_img_src(html):#这里html是网页源码
    soup = BeautifulSoup(html, 'lxml')#soup是beautifulsoup解析过的html
    titles = soup.select('title')[0].get_text()#有可能会有其他的title,但是不需要,这里指需要第一个,
    #print("这里分割:", titles)#日本漫画】色列本子之[U.R.C] 慧ちゃん限定(2)_少女漫画站,(2)是页码
    title_page = titles.split('_', 2)[0]#titles是创立图片时需要使用的名字,title是创立文件夹需要的名字
    #print("title_page=",title_page)
    title = title_page.split('(', 2)[0]#保留(左边的部分
    #print("title=", title)
    img_span = soup.find('ul', {'class': 'mnlt'})
    if img_span:
        img_src = img_span.find_all('img', src=re.compile('^http://tu.goldlevi.com/svmhz/uploads2/allimg/[0-9]{1,}/(.*?).jpg$'))
        if img_src:
            for url in img_src:
                urls = url['src']
                down_image(urls, title, titles)#调用了down_image函数


def down_image(url, title, titles):#根据入口链接对漫画进行下载
    #url = http: // tu.goldlevi.com / svmhz / uploads2 / allimg / 161129 / 2 - 161129102620.j
    #title = 莲子酱绅士福利本 动漫本子邪恶少女漫画
    #titles = 莲子酱绅士福利本 动漫本子邪恶少女漫画_少女漫画站
    try:
        response = requests.get(url)
        if response.status_code == 200:
            save_image(response.content, title, url, titles)#调用函数进行对图片的保存
        print('链接异常')
        return None
    except RequestException:
        print('爬虫异常')
        return None


def save_image(content, title, url, titles):
    path = 'D:/pic/' + str(title)#确定保存在哪个文件夹下面
    if not os.path.exists(path):#如果文件夹不存在,就进行保存
        os.mkdir(path)
    file_name = '{0}/{1}.{2}'.format(path, titles, '.jpg')#{1}.{2}中{1}是名字,{2}是后缀,{0}是文件夹路径
    #print("file_name=",file_name)
    if not os.path.exists(file_name):#如果以该文件为名义的文件不存在
        with open(file_name, 'wb') as f:#读写建立一个新的二进制文件
            f.write(content)
            print('保存漫画成功', title, url)
            f.close()


def main(offset):
    html = get_index_page(offset)#html初始化
    for url in parser_index_page(html):#这里的html是按了F12之后出现的网页源代码,in后面是深层次便利后的 子网页连接的集合
        html = parser_image_page(url)#html代表总页码相关的字符串,例如“本漫画共有89页”
        total = int(re.compile('(\d+)').search(html).group(1))#从带有总页码信息的文字字符串中提取出纯数字信息,提取后结果为:89
        for img_url in get_image_page(url, total):#传入参数,url=某本特定的漫画书入口网址,total:该漫画书页码,该句对哪本漫画书中的第几页进行了精确的确定
            #该函数返回该特定的漫画书中各个页码对应的连接的集合****
            htmls = get_image_src(img_url)#get_image_src是获取url并且在函数里面调用下载函数
            parser_img_src(htmls)
            ##两重for循环的话
##第一个for循环把某个特定漫画的总页码数total和该特定漫画在首页的入口url递给第二个for循环
##那么有一重是负责遍历首页的各种连接的
##有一重是用来遍历该连接中的各种子连接的
##第二个for循环是用来遍历某个特定漫画的各个页并进行下载的
##第一个for是用来遍历首页推荐的各种漫画的


if __name__ == '__main__':
    groups = [x for x in range(1, 86)]#爬http://www.svmhz.com/shaonvmanhua/的一部分,总共有85页
    pool = Pool()
    pool.map(main, groups)#

————————————————————————————————————————————————————



Reference:

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/172254.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 【转载】C#之C#、.NET Framework、CLR的关系

    【转载】C#之C#、.NET Framework、CLR的关系

    2021年11月20日
    295
  • JavaScript计时器函数用法

    JavaScript计时器函数用法文章出自个人博客 amp amp lt amp amp gt 转载请申明 Javascript 中和大多数语言一样 存在计时函数 使某语句或函数不用立即执行 可以延时设定的时间值之后再执行 setTimeout 方法这个函数表示括号中的代码 延时指定时间后再执行 格式为 setTimeout function time 其中 time 的单位是毫秒 例如 functionfx

    2025年7月1日
    2
  • 回文字符串判断以及最长回文字符串长度判断「建议收藏」

    回文字符串判断以及最长回文字符串长度判断「建议收藏」回文字符串,就是正着反着读都一样的字符串。1、回文字符串判断假如这个字符串为奇数长度的回文字符串,则除了最中间的字符外,其左右的字符串两两相同。假如这个字符串为偶数长度的回文字符串,则其左右完全对称。代码如下:#include<iostream>#include<string>usingnamespacestd;boolpalindrome(strin…

    2022年6月5日
    30
  • 免费的ASP.NET AJAX 培训

    免费的ASP.NET AJAX 培训  好久没有写blog了,在这里感慨一下先 ;-))  最近BradAbrams 做了个关于ajax的E-Learning ,内容通俗易懂,估计这个教程2个小时可以完成。在学Ajax的朋友不妨看一下;点击here ,关于这个elearning的详细信息FreeASP.NETAJAXOnlineTraining在这里也郁闷一下,在asp.netajax1.0中列表

    2025年10月26日
    3
  • Hive修改字段类型_hive表添加字段sql

    Hive修改字段类型_hive表添加字段sqlhive修改字段类型语句:altertable表名changecolumn原字段名新字段名字段类型;altertableuser_chainchangecolumnu_registeru_registedate;(u_register原类型为string类型)这样修改会报一个错误:FAILED:ExecutionError,returncode1fro…

    2025年9月18日
    9
  • phpstorm2021.5激活码【注册码】

    phpstorm2021.5激活码【注册码】,https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月19日
    45

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号