python爬取网站所有资源

@python爬取网站所有资源
由于我的python爬取网站资源博客https://editor.csdn.net/md/?articleId=110483364,在后台有多人私信我在爬取过程中出现了很多问题,比如说遇到服务器验证返回乱码、或者直接爬取的html是无效的,现在我们更加深入一些,不仅仅是爬取某一个网页的资源,我们要做的是将整个网站所有的资源打包。就算它有上百万张照片、视频,我们也能在一小段程序代码中将它们收入囊中。

一、兵欲善其事,必先利其器

有一个强大而且全面的headers(请求头)是一切爬虫的利器之一
首先我们要了解http\https协议,以及服务器端和客户端之间的某种关系。就拿客户端来说,我们的浏览器(browser)就相当于一个客户端,我们在浏览器上访问网站,其实就是客户端向服务器发送请求(request),当我们正常在浏览器页面上看到的内容,其实就是服务器端(servers)根据浏览器的请求而反馈给浏览器的一种响应(response),不管你请求的url是否存在,浏览器都会给你一个响应,即使这个响应会使404(页面不存在)、405(method not allowed)等等。也可以这样说,客户端和服务器端是有求必应。而服务器端是怎么样根据我们的请求而反馈给我们响应呢?
那就是请求头(request headers),兵欲善其事,必先利其器,一个强大而且全面的请求头会给我们的爬虫节省很多不必要的麻烦。
先看看我们的目标:
《python爬取网站所有资源》
爬取这个网站上所有的资源,包括照片、视频、tet文档等等。在这里我不能将这个网站的首页放出来(毕竟涉黄),在此,我们只讲技术,不讲内容。
我的上一篇“python爬取资源网站资源”博客就是基于这个网站写的,但是发现这个网站的域名一直在更改,很多人用我的代码直接去爬取会出现验证的问题,下面我们将更加深层次的讲解一下我的解决过程:
先来看一下headers:
《python爬取网站所有资源》

在此我们要非常注意一个细节:Referer。我在上一篇博客中的headers中没有Referer属性,所以你运行源代码后会被阻拦在首页中,返回的html文档也是一堆没有用的代码,那是因为服务器端识别了你为爬虫,所以将你拒之门外。那么服务器是怎么知道我是爬虫呢?我不是已经写了headers了吗?
后来我查看了一下这个网站,聪明的我发现了这个问题,那就是Referer。当我在headers里加了Referer属性,爬取过程是非常顺利的。来看一下headers源代码:

def get_html(url):
    headers={ 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36 QIHU 360SE','Referer':\
	'https://www.16df.xyz/home.html'}
    response=requests.get(url,params=headers)
    if response.status_code==200:
        print("状态码成功")
        if "验证" in response.text:
            print("被验证")
            return None
        else:
            return response.text
    else:
       print("状态码失败"+url)
       print(response.status_code)

二、知己知彼,百战不殆

“纵观世界军事史,没有一场战争是不伟大的,也没有一场战争是没有战术的”—————崔亮
上边这句话是我说的,在爬虫中也是一样,爬虫就是服务器端的码农和客户端的码农之间的相互较量,那么我想要爬取服务器端的资源,那么我就要知道如何去攻破“资源”的城池。

我们打开网站的首页,打开网页源代码,发现:
《python爬取网站所有资源》
《python爬取网站所有资源》
太好了!这个网站建设者真的是为爬虫而生的,所有的资源罗列得整整齐齐,太感动了!哈哈哈!!!
那个a标签不是超链接吗?href就是它的地址呀!!!
考虑到我的电脑内存有限,这网站有几万张照片,如果全下载到我电脑里,那我电脑不起烟了呀,所以我便把它的地址给爬出来了,以后想要看就随便打开一个链接,多么方便呀!
来吧,直接上代码:

import re
from bs4 import BeautifulSoup
import requests
from time import sleep

def get_html(url):
    headers={ 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36 QIHU 360SE','Referer':\
	'https://www.16df.xyz/home.html'}
    response=requests.get(url,params=headers)
    if response.status_code==200:
        print("状态码成功")
        if "验证" in response.text:
            print("被验证")
            return None
        else:
            return response.text
    else:
       print("状态码失败"+url)
       print(response.status_code)
       
       
def parse_html(html,name):
    soup=BeautifulSoup(html,'lxml')
    results=soup.select(name)
    with open('pachong3_csdn.txt','a+') as f:
        print('*'*50+'正在获取地址中'+'*'*50)
        for result in results:
            url='https://www.16df.xyz'
            print(url+result['href'])
            f.write(url+result['href']+'\n')
            print('*'*50+'下载成功'+'*'*50)

def parse_html_full(html,name):
    soup=BeautifulSoup(html,'lxml')
    results=soup.select(name)
    print('*'*50+'正在读取ing'+'*'*50)
    with open('pachong4_csdn.txt','a+') as f:
        print('*'*50+'正在获取地址中'+'*'*50)
        for result in results:
            if result['src']:
                print(result['src'])
                f.write(result['src']+'\n')
                print('*'*50+'下载成功'+'*'*50)
            else:
                pass
            
            

url='https://www.16df.xyz/pic/'
for i in range(1,8):
    url_path=url+str(i)
    print(url_path+'获取html中')
    html=get_html(url_path)
    if html==None:
        print('失败')
        pass
    else:
        parse_html(html,name='a')
with open('pachong3_csdn.txt')as f:
    freadlines=f.readlines()
    for readline in freadlines:
        url_path_1=readline.rstrip()
        if 'html' in url_path_1:
            print('*'*50+'正在获取'+url_path_1+'*'*50)
            html_1=get_html(url_path_1)
            if html_1==None:
                print('失败')
                pass
            else:
                parse_html_full(html_1,name='img')
                sleep(3)
        else:
            pass

朋友们,运行这段代码,有你意想不到的事情发生!(可能时间会很长,毕竟光图片链接我就爬了十几分钟呢)。
那么让机智的我来解释一下这个结构吧!
1.请求头:
在请求头里加了一个Rerferer属性

headers={ 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36 QIHU 360SE','Referer':\
	'https://www.16df.xyz/home.html'}

这是为了应对服务器端的验证机制,什么意思呢?服务器那边需要Rerferer为本网站url时,才能够正常访问,所以我就伪装了一下,调用get_html(url)时,即获得每个url的html时,我都会使用正确伪装的headers获得正确的html。
2.来看这段html代码:
《python爬取网站所有资源》
很明显,网站把图片分为7个部分,那么我们就可以设置它的url格式了,如下图:

url='https://www.16df.xyz/pic/'
for i in range(1,8):
    url_path=url+str(i)
    print(url_path+'获取html中')
    html=get_html(url_path)
    if html==None:
        print('失败')
        pass
    else:
        parse_html(html,name='a')

3.解析html

def parse_html(html,name):
    soup=BeautifulSoup(html,'lxml')
    results=soup.select(name)
    with open('pachong3_csdn.txt','a+') as f:
        print('*'*50+'正在获取地址中'+'*'*50)
        for result in results:
            url='https://www.16df.xyz'
            print(url+result['href'])
            f.write(url+result['href']+'\n')
            print('*'*50+'下载成功'+'*'*50)

def parse_html_full(html,name):
    soup=BeautifulSoup(html,'lxml')
    results=soup.select(name)
    print('*'*50+'正在读取ing'+'*'*50)
    with open('pachong4_csdn.txt','a+') as f:
        print('*'*50+'正在获取地址中'+'*'*50)
        for result in results:
            if result['src']:
                print(result['src'])
                f.write(result['src']+'\n')
                print('*'*50+'下载成功'+'*'*50)
            else:
                pass

为什么要设置两个解析函数呢?
在实际爬取过程中,我们分成了两个阶段。第一个阶段为爬取首页html,获取总链接,第二阶段为遍历总链接,获得的txt文档。其实两个解析函数可以写到一块儿,就是有些繁琐,所以我使用了两个解析函数。
4.保存目标资源
由于资源过多,我们只选择此网站的照片链接,将它写进一个txt文件中。代码:

with open('pachong3_csdn.txt')as f:
    freadlines=f.readlines()
    for readline in freadlines:
        url_path_1=readline.rstrip()
        if 'html' in url_path_1:
            print('*'*50+'正在获取'+url_path_1+'*'*50)
            html_1=get_html(url_path_1)
            if html_1==None:
                print('失败')
                pass
            else:
                parse_html_full(html_1,name='img')
                sleep(3)
        else:
            pass

在此,我设置了time.sleep()方法,意为防止服务器端响应出现问题,或者出现timeout问题。为了将整个下载工程可视化,我在下载每个资源之前,都会将下载进程打印到控制台上。

三、烹羊宰牛、凯旋归来

虽然只下载了这个网站的图片链接,但也整整花了我十多分钟,最后还是我迫不得已才点击停止的,可想一下,资源网站就是不一样,全是资源,哈哈哈!!!l来看一下成果:
《python爬取网站所有资源》
《python爬取网站所有资源》
《python爬取网站所有资源》
随便打开任何一个链接,都会有意想不到的事情发生哦

《python爬取网站所有资源》
有多少张图片已经不重要了,重要的是我们只讨论技术,其它都不重要呢!是不是get到一项新技能呢?
如果对我的文章感兴趣,请为我点一个赞,如果有python的知识需要了解或探讨,可以加本人微信:cuiliang1666457052

    原文作者:穆穆Max
    原文地址: https://blog.csdn.net/weixin_52134263/article/details/110734304
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞