返回顶部
首页 > 资讯 > 后端开发 > Python >Python爬虫入门教程: 27270图
  • 893
分享到

Python爬虫入门教程: 27270图

爬虫入门教程Python 2023-01-31 00:01:59 893人浏览 安东尼

Python 官方文档:入门教程 => 点击学习

摘要

今天继续爬取一个网站,Http://www.27270.com/ent/meinvtupian/ 这个网站具备反爬,so我们下载的代码有些地方处理的也不是很到位,大家重点学习思路,有啥建议可以在评论的地方跟我说说。   为了以后的网

今天继续爬取一个网站,Http://www.27270.com/ent/meinvtupian/ 这个网站具备反爬,so我们下载的代码有些地方处理的也不是很到位,大家重点学习思路,有啥建议可以在评论的地方跟我说说。


 

为了以后的网络请求操作方向,我们这次简单的进行一些代码的封装操作。

在这里你可以先去安装一个叫做 retrying 的模块

pip install retrying

这个模块的具体使用,自己去百度吧。嘿嘿哒~

在这里我使用了一个随机产生user_agent的方法

import requests
from retrying import retry
import random
import datetime

class R:

    def __init__(self,method="get",params=None,headers=None,cookies=None):
        # do something


    def get_headers(self):
        user_agent_list = [ \
            "Mozilla/5.0 (windows NT 6.1; WOW64) AppleWEBKit/537.1 (Khtml, like Gecko) Chrome/22.0.1207.1 Safari/537.1" \
            "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11", \
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6", \
            "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6", \
            "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1", \
            "Mozilla/5.0 (X11; linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5", \
            "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5", \
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", \
            "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", \
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", \
            "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", \
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", \
            "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", \
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", \
            "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", \
            "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3", \
            "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24", \
            "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"
        ]
        UserAgent = random.choice(user_agent_list)
        headers = {'User-Agent': UserAgent}
        return headers
    #other code

 

retrying 最简单的使用就是给你想不断重试的方法加上 装饰器 @retry

在这里,我希望网络请求模块尝试3次之后,在报错!

同时在R类初始化方法中增加一些必备的参数,你可以直接看下面的代码

__retrying_requests 方法为私有方法,其中根据get和post方式进行逻辑判断


import requests
from retrying import retry
import random
import datetime

class R:

    def __init__(self,method="get",params=None,headers=None,cookies=None):
        #do something

    def get_headers(self):
        # do something
    @retry(stop_max_attempt_number=3)
    def __retrying_requests(self,url):
        if self.__method == "get":
            response = requests.get(url,headers=self.__headers,cookies=self.__cookies,timeout=3)
        else:
            response = requests.post(url,params=self.__params,headers=self.__headers,cookies=self.__cookies,timeout=3)
        return response.content

   
    # other code

 

网络请求的方法已经声明完毕,并且返回 response.content 数据流

下面基于这个私有方法,增加一个获取网络文本的方法和一个获取网络文件的方法。同步完善类的初始化方法,在开发中发现,我们要爬取的网页编码是gb2312 所以还需要给某些方法增加一个编码参数

import requests
from retrying import retry
import random
import datetime

class R:
    # 类的初始化方法
    def __init__(self,method="get",params=None,headers=None,cookies=None):
        self.__method = method
        myheaders = self.get_headers()
        if headers is not None:
            myheaders.update(headers)
        self.__headers = myheaders
        self.__cookies = cookies
        self.__params = params


    def get_headers(self):
       # do something

    @retry(stop_max_attempt_number=3)
    def __retrying_requests(self,url):
        # do something

    # get请求
    def get_content(self,url,charset="utf-8"):
        try:
            html_str = self.__retrying_requests(url).decode(charset)
        except:
            html_str = None
        return html_str

    def get_file(self,file_url):
        try:
            file = self.__retrying_requests(file_url)
        except:
            file = None
        return file

#小编整理一套python资料和pdf,有需要Python学习资料可以加学习群:1004391443,反正闲着也是闲着呢,不如学点东西啦~~

  

 

到此,这个R类已经被我们完善了,完整的代码,你应该从上面拼凑起来,你也可以直接翻到文章最后面,去GitHub上直接查阅。

接下来,就是比较重要的爬虫代码部分了。这一次,我们可以简单的使用一下类和对象,并且加上简单的多线程操作。

首先,创建一个 ImageList 类,这个类第一件事情,需要获取我们爬取页面的总页码数目

在这里插入图片描述

这个步骤比较简单

  1. 获取网页源码
  2. 正则匹配末页元素
  3. 提取数字
import http_help as hh   # 这个http_help 是我上面写到的那个R类
import re
import threading
import time
import os
import requests

# 获取所有待爬取的URL列表
class ImageList():
    def __init__(self):
        self.__start = "http://www.27270.com/ent/meinvtupian/list_11_{}.html"  # URL模板
        # 头文件
        self.__headers = {"Referer":"http://www.27270.com/ent/meinvtupian/",
                          "Host":"www.27270.com"
                          }
        self.__res = hh.R(headers=self.__headers)  # 初始化访问请求
    def run(self):
        page_count =  int(self.get_page_count())

        if page_count==0:
            return
        urls = [self.__start.fORMat(i) for i in range(1,page_count)]
        return urls


    # 正则表达式匹配末页,分析页码
    def get_page_count(self):
        # 注意这个地方需要传入编码
        content = self.__res.get_content(self.__start.format("1"),"gb2312")
        pattern = re.compile("<li><a href='list_11_(\d+?).html' target='_self'>末页</a></li>")
        search_text = pattern.search(content)
        if search_text is not None:
            count = search_text.group(1)
            return count
        else:
            return 0
if __name__ == '__main__':
    img = ImageList()
    urls = img.run()

 

上面的代码注意get_page_count方法,该方法已经获取到了末尾的页码

在这里插入图片描述

我们在run方法内部,通过一个列表生成器

urls = [self.__start.format(i) for i in range(1,page_count)]

批量把要爬取的所有链接都生成完毕。

27270图片----分析上面爬取到的URL列表,捕获详情页

我们采用生产者和消费者模型,就是一个抓取链接图片,一个下载图片,采用多线程的方式进行操作,需要首先引入

import threading
import time

完整代码如下

import http_help as hh
import re
import threading
import time
import os
import requests

urls_lock = threading.Lock()  #url操作
imgs_lock = threading.Lock()  #图片操作锁

imgs_start_urls = []


class Product(threading.Thread):
    # 类的初始化方法
    def __init__(self,urls):
        threading.Thread.__init__(self)
        self.__urls = urls
        self.__headers = {"Referer":"http://www.27270.com/ent/meinvtupian/",
                          "Host":"www.27270.com"
                          }

        self.__res = hh.R(headers=self.__headers)

    # 链接抓取失败之后重新加入urls列表中
    def add_fail_url(self,url):
        print("{}该URL抓取失败".format(url))
        global urls_lock
        if urls_lock.acquire():
            self.__urls.insert(0, url)
            urls_lock.release()  # 解锁
    
    # 线程主要方法
    def run(self):
        print("*"*100)
        while True:
            global urls_lock,imgs_start_urls
            if len(self.__urls)>0:
                if urls_lock.acquire():   # 锁定
                    last_url = self.__urls.pop()   # 获取urls里面最后一个url,并且删除
                    urls_lock.release()  # 解锁

                print("正在操作{}".format(last_url))

                content = self.__res.get_content(last_url,"gb2312")   # 页面注意编码是gb2312其他格式报错
                if content is not  None:
                    html = self.get_page_list(content)

                    if len(html) == 0:
                        self.add_fail_url(last_url)
                    else:
                        if imgs_lock.acquire():
                            imgs_start_urls.extend(html)    # 爬取到图片之后,把他放在待下载的图片列表里面
                            imgs_lock.release()

                    time.sleep(5)
                else:
                    self.add_fail_url(last_url)

            else:
                print("所有链接已经运行完毕")
                break





    def get_page_list(self,content):
        # 正则表达式
        pattern = re.compile('<li> <a href="(.*?)" title="(.*?)" class="MMPic" target="_blank">.*?</li>')
        list_page = re.findall(pattern, content)

        return list_page

 

上述代码中比较重要的有
threading.Lock() 锁的使用,在多个线程之间操作全局变量,需要进行及时的锁定;
其他的注意内容,我已经添加在注释里面,只要你按着步骤一点点的写,并且加入一些自己微妙的理解,就可以搞定。

到现在为止,我们已经抓取到了所有的图片地址,我把他存放在了一个全局的变量里面 imgs_start_urls
那么现在又来了

这个列表里面存放的是 http://www.27270.com/ent/meinvtupian/2018/298392.html 这样的地址,当你打开这个页面之后,你会发现只有一张图片 ,并且下面有个分页。
在这里插入图片描述
在这里插入图片描述

点击分页之后,就知道规律了

http://www.27270.com/ent/meinvtupian/2018/298392.html 
http://www.27270.com/ent/meinvtupian/2018/298392_2.html 
http://www.27270.com/ent/meinvtupian/2018/298392_3.html 
http://www.27270.com/ent/meinvtupian/2018/298392_4.html 
....

当你进行多次尝试之后,你会发现,后面的链接完全可以靠拼接完成,如果没有这个页面,那么他会显示?

在这里插入图片描述

好了,如果你进行了上面的操作,你应该知道接下来怎么实现啦!

我把所有的代码,都直接贴在下面,还是用注释的方式给大家把最重要的地方标注出来

class Consumer(threading.Thread):
    # 初始化
    def __init__(self):
        threading.Thread.__init__(self)
        self.__headers = {"Referer": "http://www.27270.com/ent/meinvtupian/",
                          "Host": "www.27270.com"}
        self.__res = hh.R(headers=self.__headers)

    # 图片下载方法
    def download_img(self,filder,img_down_url,filename):
        file_path = "./downs/{}".format(filder)
        
        # 判断目录是否存在,存在创建
        if not os.path.exists(file_path):
            os.mkdir(file_path)  # 创建目录

        if os.path.exists("./downs/{}/{}".format(filder,filename)):
            return
        else:
            try:
                # 这个地方host设置是个坑,因为图片为了防止盗链,存放在另一个服务器上面
                img = requests.get(img_down_url,headers={"Host":"t2.hddhhn.com"},timeout=3)
            except Exception as e:
                print(e)

            print("{}写入图片".format(img_down_url))
            try:
                # 图片写入不在赘述
                with open("./downs/{}/{}".format(filder,filename),"wb+") as f:
                    f.write(img.content)
            except Exception as e:
                print(e)
                return





    def run(self):

        while True:
            global imgs_start_urls,imgs_lock

            if len(imgs_start_urls)>0:
                if imgs_lock.acquire():  # 锁定
                    img_url = imgs_start_urls[0]   #获取到链接之后
                    del imgs_start_urls[0]  # 删掉第0项
                    imgs_lock.release()  # 解锁
            else:
                continue

            # http://www.27270.com/ent/meinvtupian/2018/295631_1.html

            #print("图片开始下载")
            img_url = img_url[0]
            start_index = 1
            base_url = img_url[0:img_url.rindex(".")]    # 字符串可以当成列表进行切片操作

            while True:

                img_url ="{}_{}.html".format(base_url,start_index)   # url拼接
                content = self.__res.get_content(img_url,charset="gbk")   # 这个地方获取内容,采用了gbk编码
                if content is not None:
                    pattern = re.compile('<div class="articleV4Body" id="picBody">[\s\S.]*?img alt="(.*?)".*? src="(.*?)" />')
                    # 匹配图片,匹配不到就代表本次操作已经完毕
                    img_down_url = pattern.search(content)  # 获取到了图片地址

                    if img_down_url is not None:
                        filder = img_down_url.group(1)
                        img_down_url = img_down_url.group(2)
                        filename = img_down_url[img_down_url.rindex("/")+1:]
                        self.download_img(filder,img_down_url,filename)  #下载图片

                    else:
                        print("-"*100)
                        print(content)
                        break # 终止循环体

                else:
                    print("{}链接加载失败".format(img_url))

                    if imgs_lock.acquire():  # 锁定
                        imgs_start_urls.append(img_url)
                        imgs_lock.release()  # 解锁

                start_index+=1   # 上文描述中,这个地方需要不断进行+1操作

 

所有的代码都在上面了,关键的地方我尽量加上了标注,你可以细细的看一下,实在看不明白,就多敲几遍,因为没有特别复杂的地方,好多都是逻辑。

最后附上main部分的代码,让我们的代码跑起来

if __name__ == '__main__':

    img = ImageList()
    urls = img.run()
    for i in range(1,2):
        p = Product(urls)
        p.start()

    for i in range(1,2):
        c = Consumer()
        c.start()

 

一会过后,就慢慢收图吧
在这里插入图片描述

--结束END--

本文标题: Python爬虫入门教程: 27270图

本文链接: https://lsjlt.com/news/182182.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Python爬虫入门教程: 27270图
    今天继续爬取一个网站,http://www.27270.com/ent/meinvtupian/ 这个网站具备反爬,so我们下载的代码有些地方处理的也不是很到位,大家重点学习思路,有啥建议可以在评论的地方跟我说说。   为了以后的网...
    99+
    2023-01-31
    爬虫 入门教程 Python
  • Python爬虫入门教程 57-100
    滑动验证码介绍 本篇博客涉及到的验证码为滑动验证码,不同于极验证,本验证码难度略低,需要的将滑块拖动到矩形区域右侧即可完成。 这类验证码不常见了,官方介绍地址为:https://promotion.aliyun.com/ntms/act...
    99+
    2023-01-31
    爬虫 入门教程 Python
  • Python爬虫入门教程 48-100
    1. 爬取前的分析 mitmdump是mitmproxy的命令行接口,比Fiddler、Charles等工具方便的地方是它可以对接Python脚本。 有了它我们可以不用手动截获和分析HTTP请求和响应,只需写好请求和响应的处理逻辑即可。 ...
    99+
    2023-01-30
    爬虫 入门教程 Python
  • Python爬虫入门教程 49-100
    爬前准备工作 在开始安装Appium之前,你要先知道Appium是做什么的?Appium 是一个自动化测试开源工具,看到没,做测试用的,它有点类似Selenium,可以自动操作APP实现一系列的操作。 标记重点,可以使用python对Ap...
    99+
    2023-01-30
    爬虫 入门教程 Python
  • Python爬虫入门教程 52-100
    写在前面 关于获取文章自动发送到邮箱,这类需求其实可以写好几个网站,弄完博客园,弄CSDN,弄掘金,弄其他的,网站多的是呢~哈哈 先从博客园开始,基本需求,获取python板块下面的新文章,间隔60分钟发送一次,时间太短估摸着没有多少新博...
    99+
    2023-01-30
    爬虫 入门教程 Python
  • Python爬虫入门教程 53-100
    爬取背景 这套课程虽然叫爬虫入门类课程,但是里面涉及到的点是非常多,十分检验你的基础掌握的牢固程度,代码中的很多地方都是可以细细品味的。 为什么要写这么一个小东东呢,因为我生活在大河北,那雾霾醇厚的很,去了趟三亚,那空气,啧啧,舒服的很,...
    99+
    2023-01-31
    爬虫 入门教程 Python
  • Python爬虫入门教程 54-100
    爬虫背景 爬虫最核心的问题就是解决重复操作,当一件事情可以重复的进行的时候,就可以用爬虫来解决这个问题,今天要实现的一个基本需求是完成“博客园“ 博客的自动评论,其实原理是非常简单的,提炼一下需求 基本需求 登录博客园<不实现,登...
    99+
    2023-01-31
    爬虫 入门教程 Python
  • Python爬虫入门教程 36-100
    爬前叨叨 2018年就要结束了,还有4天,就要开始写2019年的教程了,没啥感动的,一年就这么过去了,今天要爬取一个网站叫做酷安,是一个应用商店,大家可以尝试从手机APP爬取,不过爬取APP的博客,我打算在50篇博客之后在写,所以现在就放...
    99+
    2023-01-30
    爬虫 入门教程 Python
  • Python爬虫入门教程 38-100
    爬前叨叨 今天要爬取一下正规大学名单,这些名单是教育部公布具有招生资格的高校名单,除了这些学校以外,其他招生的单位,其所招学生的学籍、发放的毕业证书国家均不予承认,也就是俗称的野鸡大学! 网址是 https://daxue.eol.cn...
    99+
    2023-01-30
    爬虫 入门教程 Python
  • Python爬虫入门教程 25-100
    1. 知乎文章图片写在前面 今天开始尝试爬取一下知乎,看一下这个网站都有什么好玩的内容可以爬取到,可能断断续续会写几篇文章,今天首先爬取最简单的,单一文章的所有回答,爬取这个没有什么难度。 找到我们要爬取的页面,我随便选了一个 https...
    99+
    2023-01-30
    爬虫 入门教程 Python
  • Python爬虫入门教程 26-100
    1. 知乎文章图片爬取器之二博客背景 昨天写了知乎文章图片爬取器的一部分代码,针对知乎问题的答案json进行了数据抓取,博客中出现了部分写死的内容,今天把那部分信息调整完毕,并且将图片下载完善到代码中去。 首先,需要获取任意知乎的问题,只...
    99+
    2023-01-30
    爬虫 入门教程 Python
  • Python爬虫入门教程 44-100
    1. 第二款抓包工具Charles安装与使用 Charles和Fiddler一样,也是一款抓包工具,比Fiddler界面更加清晰,支持多平台 1.1 官方网址 https://www.charlesproxy.com/ 1.2 下载地址...
    99+
    2023-01-30
    爬虫 入门教程 Python
  • Python爬虫入门教程 45-100
    1. Charles抓取兔儿故事背景介绍 之前已经安装了Charles,接下来我将用两篇博客简单写一下关于Charles的使用,今天抓取一下兔儿故事里面关于小猪佩奇的故事。 爬虫编写起来核心的重点是分析到链接,只要把链接分析到,剩下的就好...
    99+
    2023-01-30
    爬虫 入门教程 Python
  • Python爬虫入门教程 47-100
    1. 准备下载软件 介绍一款爬虫辅助工具mitmproxy ,mitmproxy 就是用于MITM的proxy,MITM中间人攻击。说白了就是服务器和客户机中间通讯多增加了一层。跟Fiddler和Charles最大的不同就是,mitmpr...
    99+
    2023-01-30
    爬虫 入门教程 Python
  • Python爬虫入门教程 46-100
    1. 手机收音机-爬前叨叨 今天选了一下,咱盘哪个APP呢,原计划是弄荔枝APP,结果发现竟然没有抓到数据,很遗憾,只能找个没那么圆润的了。搜了一下,找到一个手机收音机 下载量也是不错的。 2. 爬虫套路 爬虫基本套路 抓包获取链接 ...
    99+
    2023-01-30
    爬虫 入门教程 Python
  • Python爬虫入门教程 32-100
    1. B站博人传评论数据爬取简介 今天想了半天不知道抓啥,去B站看跳舞的小姐姐,忽然看到了评论,那就抓取一下B站的评论数据,视频动画那么多,也不知道抓取哪个,选了一个博人传跟火影相关的,抓取看看。网址: https://www.bilib...
    99+
    2023-01-30
    爬虫 入门教程 Python
  • Python爬虫入门教程 34-100
    爬前叨叨 已经编写了33篇爬虫文章了,如果你按着一个个的实现,你的爬虫技术已经入门,从今天开始慢慢的就要写一些有分析价值的数据了,今天我选了一个《掘金网》,我们去爬取一下他的全站用户数据。 爬取思路 获取全站用户,理论来说从1个用户作为切...
    99+
    2023-01-30
    爬虫 入门教程 Python
  • Python爬虫入门教程 29-100
    1. 手机APP数据----写在前面 继续练习pyspider的使用,最近搜索了一些这个框架的一些使用技巧,发现文档竟然挺难理解的,不过使用起来暂时没有障碍,估摸着,要在写个5篇左右关于这个框架的教程。今天教程中增加了图片的处理,你可以重...
    99+
    2023-01-30
    爬虫 入门教程 Python
  • Python爬虫入门教程 30-100
    1. 高考派大学数据----写在前面 终于写到了scrapy爬虫框架了,这个框架可以说是python爬虫框架里面出镜率最高的一个了,我们接下来重点研究一下它的使用规则。 安装过程自己百度一下,就能找到3种以上的安装手法,哪一个都可以安装上...
    99+
    2023-01-30
    爬虫 入门教程 Python
  • Python爬虫入门教程 55-100
    验证码探究 如果你是一个数据挖掘爱好者,那么验证码是你避免不过去的一个天坑,和各种验证码斗争,必然是你成长的一条道路,接下来的几篇文章,我会尽量的找到各种验证码,并且去尝试解决掉它,中间有些技术甚至我都没有见过,来吧,一起Coding吧 ...
    99+
    2023-01-31
    爬虫 入门教程 Python
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作