python爬虫学习

拟墨画扇 提交于 2020-01-22 22:54:52

利用python爬虫实现在目标网页上爬取图片的功能。

爬取图片

要实现目标功能首先考虑的是要如何实现从网上爬取图片,通过在网上参考学习我选择通过引用python的requests和re、os模块实现爬虫。下面我简单介绍一下引用这三个模块的目的,有兴趣深入了解的话网上都能搜到相关的详尽的文章。

requests是使用Apache2 licensed 许可证的HTTP库,用python编写。比urllib2模块更简洁。Request支持HTTP连接保持和连接池,支持使用cookie保持会话,支持文件上传,支持自动响应内容的编码,支持国际化的URL和POST数据自动编码,在python内置模块的基础上进行了高度的封装,从而使得python进行网络请求时,变得人性化,使用Requests可以轻而易举的完成浏览器可有的任何操作。

python 中使用正则表达式需要引入re模块,正则表达式是用来匹配处理字符串的 。
需要查找操作文件,比如说查找配置文件(从而读取配置文件的信息),查找测试报告(从而发送测试报告邮件),要对大量文件和大量路径进行操作,这就依赖于os模块。

爬虫代码

引用需要的的模块。

#_*_coding:utf-8_*_
import requests
import re
import os

接下来我们定义一个爬虫类,用于从网页上爬取图片,首先是初始化函数。定义url(爬虫目标网站的网址),从主界面获取网址字符串。headers(用于将python程序伪装成一个浏览器), 对于一些网站,如果不是从浏览器发出的请求,则得不到响应。所以,需要将爬虫程序发出的请求伪装成浏览器。 User Agent是Http协议中的一部分,中文名叫用户代理,属于头域的一部分。在访问网站时通过用户代理向服务器提供用户使用的操作系统及版本、浏览器版本及类型、浏览器的内核等信息标识。通过改写Us-er-Agent将Python爬虫伪装成浏览器。
dir_path(通过python自带的os库找到该程序源文件存放的目录),path(在源文件目录下新建一个imgs文件夹用于存放从网站上爬取的图片),判断imgs文件夹是否存在,若不存在则新建一个imgs文件夹。

    def __init__(self,url):
        self.url = url
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36'
        }
        self.dir_path = os.path.dirname(os.path.abspath(__file__))
        self.path = self.dir_path+'/imgs'
        isExists = os.path.exists(self.dir_path+'/imgs')
        # 创建目录
        if not isExists:
            os.makedirs(self.path)

然后定义下载函数。尝试requests.get指定url,下载目标网站的图像,若下载失败则打印“下载失败”。

    def download(self,url):
        try:
            res = requests.get(url,headers=self.headers)
            return res
        except Exception as E:
            print(url+'下载失败,原因:'+E)

接下来定义解析函数。解码指定网站的内容,通过正则表达式找到所有图像的网址并存入imgs_list中,最后下载imgs_list中的内容。注意将指定的网址填入字符串中。

    def parse(self,res):
        content = res.content.decode()
        # print(content)
        img_list = re.findall(r'<img.*?src="(.*?)"',content,re.S)
        img_list = ['指定的网站网址'+url for url in img_list]
        return img_list

下面是保存函数。如果imgs文件夹存在,保存通过write将下载下来的图像写入文件夹中。

 def save(self,res_img,file_name):
        if res_img:
            with open(file_name,'wb') as f:
                f.write(res_img.content)
            print(url+'下载成功')

最后运行函数run()即依次执行,下载函数、解析函数和保存函数。

    def run(self):
        # 下载
        res = self.download(self.url)
        # 解析
        url_list = self.parse(res)
        # 下载图片
        for url in url_list:
            res_img = self.download(url)
            name = url.strip().split('/').pop()
            file_name = self.path+'/'+name
            # 保存
            self.save(res_img,file_name)

下面附上主函数。填入目标网址,可以填多个到列表中。

if __name__ == '__main__':
    url_list = ['目标网址']
    for url in url_list:
        text = GetImage(url)
        text.run()

这里附上我在网上找到的测试网址,这个程序用这个网址是可以跑通的。

图形化界面

爬虫代码跑通了之后考虑做一个界面可以在界面上输入要爬的网址,并且可以浏览爬取下来的图片。因为我是单独学的图形化后来与代码强行合并的,加上代码写得不好,有些问题,暂且把成果附上,之后可能会再从新修改。

#_*_coding:utf-8_*_
import requests
import re
import os
import shutil
import time
from tkinter import * #导入tkinter模块的所有内容
import tkinter as tk,os
from PIL import Image, ImageTk
import tkinter.scrolledtext as tst

class Application2(tk.Frame):
        def __init__(self,master=None):
                self.files = os.listdir(GetImage(app.link()).path)
                self.index = 0
                self.img = ImageTk.PhotoImage(file=GetImage(app.link()).path+'\\'+self.files[self.index])
                tk.Frame.__init__(self,master)
                self.pack()
                self.createWidgets()
        def createWidgets(self):
                self.lblImage = tk.Label(self,width=800,height=600)
                self.lblImage['image'] = self.img
                self.lblImage.pack()
                self.f = tk.Frame()
                self.f.pack()
                self.btnPrev = tk.Button(self.f, text = '上一张',command = self.prev)
                self.btnPrev.pack(side = tk.LEFT)
                self.btnNext = tk.Button(self.f,text = '下一张',command = self.next)
                self.btnNext.pack(side = tk.LEFT)
                self.removeBtn = Button(self.f, text='删除', command=lambda:Remove())
                self.removeBtn.pack(side = tk.LEFT)
        def prev(self):
                self.showfile(-1)
        def next(self):
                self.showfile(1)
        def showfile(self,n):
                self.index += n
                if self.index < 0:self.index = len(self.files) - 1
                if self.index > len(self.files) - 1:self.index = 0
                self.img = ImageTk.PhotoImage(file = GetImage(app.link()).path+'\\'+self.files[self.index])
                self.lblImage['image'] = self.img


class Application(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.pack()
        self.createWidgets()

    def createWidgets(self):
        self.Label1 = Label(self, text='目标url')
        self.Label1.pack(side = LEFT)
        self.Input = Entry(self)
        self.Input.pack(side = LEFT)
        self.d = Frame()
        self.d.pack()
        self.quitButton = Button(self.d, text='爬取', command=lambda:Insert())
        self.quitButton.pack(side = LEFT)
        self.lookButton = Button(self.d, text='浏览', command=lambda: MessageBox())
        self.lookButton.pack(side = LEFT)
        self.z = Frame()
        self.z.pack()
        self.text = tst.ScrolledText(self.z, width=50,height=20)
        self.text.pack(side = LEFT)
    def link(self):
        url = self.Input.get()
        return url
    def Insert(self):
        while True:
             self.ScrolledText.insert(END,'https://www.yangqq.com/下载成功\n')
             self.ScrolledText.update()
             time.sleep(1)

class GetImage(object):
    def __init__(self,url):
        self.url = url
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36'
        }
        self.dir_path = os.path.dirname(os.path.abspath(__file__))
        self.path = self.dir_path+'/imgs'
        isExists = os.path.exists(self.dir_path+'/imgs')
        # 创建目录
        if not isExists:
            os.makedirs(self.path)

    def download(self,url):
        try:
            res = requests.get(url,headers=self.headers)
            return res
        except Exception as E:
            print(url+'下载失败,原因:'+E)


    def parse(self,res):
        content = res.content.decode()
        # print(content)
        img_list = re.findall(r'<img.*?src="(.*?)"',content,re.S)
        img_list = [app.link()+url for url in img_list]
        return img_list

    def save(self,res_img,file_name):
        if res_img:
            with open(file_name,'wb') as f:
                f.write(res_img.content)
            print(url+'下载成功')

    def run(self):
        # 下载
        res = self.download(self.url)
        # 解析
        url_list = self.parse(res)
        # 下载图片
        for url in url_list:
            res_img = self.download(url)
            name = url.strip().split('/').pop()
            file_name = self.path+'/'+name
            # 保存
            self.save(res_img,file_name)

if __name__ == '__main__':
        def MessageBox():
                top = tk.Toplevel()
                top.title('图片浏览')
                app2 = Application2(master = top)
        def Remove():
                path = GetImage(app.link()).path
                if(os.path.exists(path)):
                        shutil.rmtree(GetImage(app.link()).path+'/'+app.link().strip().split('/').pop())
        def Insert():
                app.quit()
                app.text.insert(END,'https://www.yangqq.com/下载成功\n')
                app.text.update()
                time.sleep(1)
        app = Application()
        # 设置窗口标题:
        app.master.title('图像爬虫')
        #设置窗口大小
        app.master.geometry("800x600")
        # 主消息循环:
        app.mainloop()
        url_list = [app.link()]
        for url in url_list:
            text = GetImage(url)
            text.run()

图形化界面我是用tkinter写的,其中一些功能我虽然写了,但没有实现,可能代码写得还是有问题,例如将爬虫的信息实时打印到用户界面没实现。

总结

这是学期末课设的题目,我写进博客一方面是想方便我以后复习,另一方面是可以给别人借鉴学习,文章如有错误敬请见谅,欢迎找我讨论学习。下面是我爬虫代码的借鉴文章:
https://www.jianshu.com/p/074fb56cf0cc

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!