用Python爬虫爬百度百科和百度图片

0.简介

 

2020年的一个Python大作业,用到一些爬虫知识,分享给大家

1.获得信息函数功能

这个函数初步实现了百度百科和百度图片的部分功能,用户可以输入一些常用的关键字来获得信息。相比于打开网页,这个达到了批量处理的功能,可以自动将信息生成Excel表格,方便对信息的存储。而且获取图片功能,可以一次下载许多图片。

下面是GUI界面展示:

下图是百度百科关于python的一些内容,我们想把python的简介和他的一些基本信息保存下来,就不用一个一个输入内容。

下图是用python爬虫得到的结果:

这样的到的结果和原网页内容一致

这个功能算比较完整的完成了

而你只需要在如下窗口输入python点击提交,然后点击获得资料即可(注意要先提交,出现提示信息提交成功后再点击获得信息)

生成的Excel表格在当前程序文件夹内,也可以自己定义文件在电脑内的位置

我们还可以用这个代码爬取python创始人吉多·范罗苏姆的信息:

先看百科上的:

这是用代码爬取的:

发现双方基本的信息我们都有。

以上便是的第一个功能,也是一个通用性功能,可以更高效更快捷的爬取百科的信息,并且保存在Excel表格里面,具体的实现也很简单,用了re,request和xlsxwriter库,以及字符串处理技术,在讲解的时候我会详细说明。

2. 获得图片功能

上面我们知道了python创始人的个人信息,而我们没见到他呀,具体看看他长什么样

我们可以先打开百度图片看看

下面我们用爬虫试试

输入信息之后,再输入照片数量 点击获得图片即可

我们现在来看看代码爬取的结果

图片保存在了img文件夹下,当然也可以自己修改,根据情况而定

我们发现第一张图片就是百度图片的第一张图片,而且图片的数量正好是我们输入的10,这个功能也算完成了。

下面我们试试其他的,看一看郑州大学的风景吧:

这次我们输入了10张照片,可能下载要等一会时间

下载的图片在文件夹里也可以看

这样图片的功能已经完成,具有很好的实用性和适用性

1.3深度获得信息(有一定局限性)

这个爬虫除了有普遍性的资料之外,还具有比较深度挖掘某一方面的信息的功能,先看一下界面吧,下面的获得作品信息和获奖信息是一些演员的影视作品进行爬取,和对获奖情况的爬取。

我们还是举例子看一下吧:

以周星驰导演为例看看他的经典的作品吧

周星驰作品很多,这只是一部分,后面还有很多翻页,先不一一列举了

然后还有星爷获得的奖项,奖项也是很多

接下来我们用代码爬的结果看看:

输入周星驰点击提交后,点击获得作品信息和获奖信息,就可以生成Excel表格

点开看看

这是主要作品,有很多呀,跟网页上的也是一样的

下面是获奖信息:

跟百科上也是一致的

这个功能是为了后面数据的可视化做准备,当然也可以是单独用来获得一些影视的明星的资料也是可以的,而且这个只是统计了作品和获奖记录,后续还可以开发更多功能。

1.4 可视化分析

根据1.3获得的信息,我们可以对数据可视化处理:

就以周星驰导演为例:

我们可以点击生成饼图:

也可以生成柱状图

5.代码

最重要的就是代码啦,这是好久写的了,有的地方注释较少,凑活着看

提醒一下,如果pip install wx不成功,就pip install wxpython

import requests
import re
import matplotlib.pyplot as plt
from bs4 import BeautifulSoup
from urllib.request import quote
from lxml import etree
import xlsxwriter
import time
import hashlib
from threading import Thread
import wx


class Star:
    def __init__(self, name=None):
        self.name = name


# 1.人物名称转化为HTML编码
def Get_base_url(name):
    return "https://baike.baidu.com/item/{}".format(quote(name))


headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko"
}

# 2.发送请求--用requests库,当然也可以用urllib库,通过看网页消息头知道网页是Get方式请求,而且网页是静态网页
html_data = ""


def Get_html_data(base_url):
    # 用Get方式获得一个响应
    response = requests.get(url=base_url, headers=headers)
    # print(response)  # 可以打印查看状态
    html_data = response.text
    # print(html_data) # 可以通过打印,看看网页源代码,看是否有乱码的情况
    return html_data


# 3.解析数据(通过通过正则表达式,把自己想要的信息找到)用parser库专门用来解析
# (1)获得基本信息
def Get_information(html_data, star):
    # (1)数据类型转换
    bs = BeautifulSoup(html_data, 'html.parser')
    html = etree.HTML(html_data)
    base_information = []
    base_information_list = html.xpath('//div[contains(@class,"lemma-summary")]//text()')
    for item in base_information_list:
        item = str(item)
        item = item.strip()
        base_information.append(item)
    Base_Information = ''.join(base_information)
    star.Base_Information = Base_Information
    index_information = bs.find_all("dt", {'class': "basicInfo-item name"})
    index_list = []
    information_list = []
    Information = []
    # (2)存基本信息
    for item in index_information:
        # print(item.text.strip())
        index_list.append(item.text.strip())
    information = bs.find_all("dd", {'class': "basicInfo-item value"})
    for item in information:
        # print(item.text.strip())
        information_list.append(item.text.strip())
    # print(information)
    for i in range(len(information_list)):
        Information.append((index_list[i], information_list[i]))
    # print(Information)
    star.Information = Information


# (2)解析作品,获得作品信息
find_movie = re.compile(r'<b class="title">(.*?)</b>')
find_movie_date = re.compile(r'<b>(.*)</b>')


def Get_movie(html_data, star):
    bs = BeautifulSoup(html_data, 'html.parser')
    movie = bs.find_all("ul", {"class": "starWorksList"})
    movie_tittle = []
    movie_date = []
    movie_date_year = []
    for item in movie:
        # print(item)
        # print('\n')
        data = re.findall(find_movie, str(item))
        # print(data)
        # print('\n')
        for d in data:
            if '<' in d:
                tittle = d.split('>')[1].split('<')[0]
            else:
                tittle = d
            # print(tittle)
            movie_tittle.append(tittle)
        date = re.findall(find_movie_date, str(item))
        movie_data_left = date[0].split('<')[0]
        movie_date.append(movie_data_left)
        if (len(date) == 2):
            movie_data_right = date[1].split('<')[0]
            movie_date.append(movie_data_right)
    # print(movie_date)
    for item in movie_date:
        movie_date_year.append(item.split('-')[0])
    # print(movie_date_year)
    # 创建列表,二元组存储对象的作品
    Data = []
    length = len(movie_tittle)
    for i in range(0, length):
        Data.append((movie_date[i], movie_tittle[i], movie_date_year[i]))
    star.Data = Data
    # print(Data)
    return star


# (3)获得获奖信息
find_reward_date = re.compile(r'<span class="first column">(.*?)</span>')
find_reward_name = re.compile(r'<span class="column">(.*?)</span')


def Get_reward(html_data, star):
    bs = BeautifulSoup(html_data, 'html.parser')
    reward_index = bs.find_all("li", {"class": "row"})
    # print(reward_index)
    # print('\n')
    reward = []
    reward_date_list = []
    reward_name_list = []
    reward_date_list_year = []
    for item in reward_index:
        i = item.text.strip()
        reward_date_list.append(i.split()[1])
        reward_name_list.append(i.split()[2])
    # print(reward_date_list)
    # print(reward_name_list)
    for item in reward_date_list:
        reward_date_list_year.append(item.split('-')[0])
    # print(reward_date_list_year)
    for i in range(len(reward_date_list)):
        reward.append((reward_date_list[i], reward_name_list[i], reward_date_list_year[i]))
    star.reward = reward
    return star


# 4.获取图片
class BaiDu_picture:
    """
    爬取百度图片
    """

    def __init__(self, name, page, number):
        self.start_time = time.time()
        self.name = name
        self.page = page
        self.url = 'https://image.baidu.com/search/acjson'
        self.header = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko"
        }
        self.num = 0
        self.number = number

    def queryset(self):
        """
        将字符串转换为查询字符串形式
        """
        pn = 0
        for i in range(int(self.page)):
            pn += 60 * i
            name = {'word': self.name, 'pn': pn, 'tn': 'resultjson_com', 'ipn': 'rj', 'rn': 60}
            url = self.url
            self.getrequest(url, name)

    def getrequest(self, url, data):
        """
        发送请求
        """
        # print('[INFO]: 开始发送请求:' + url)
        ret = requests.get(url, headers=self.header, params=data)

        # if str(ret.status_code) == '200':
        # print('[INFO]: request 200 ok :' + ret.url)
        # else:
        # print('[INFO]: request {}, {}'.format(ret.status_code, ret.url))

        response = ret.content.decode()
        img_links = re.findall(r'thumbURL.*?\.jpg', response)
        links = []
        # 提取url
        for i in range(len(img_links)):
            if i == int(self.number):
                break
            links.append(img_links[i][11:])
        self.thread(links)

    def saveimage(self, link):
        """
        保存图片
        """
        m = hashlib.md5()
        m.update(link.encode())
        name = m.hexdigest()
        ret = requests.get(link, headers=self.header)
        image_content = ret.content
        name = name + '.jpg'
        with open('img\\' + name, 'wb') as f:
            f.write(image_content)

    def thread(self, links):
        """多线程"""
        self.num += 1
        for i, link in enumerate(links):
            if link:
                time.sleep(0.5)
                t = Thread(target=self.saveimage, args=(link,))
                t.start()
                t.join()
            self.num += 1
        # print('一共进行了{}次请求'.format(self.num))

    def __del__(self):
        end_time = time.time()
        # print('一共花费时间:{}(单位秒)'.format(end_time - self.start_time))


def movie_amount_show(star):
    amount = []
    date = set()
    movie_count = []
    for item in star.Data:
        date.add(item[2])
        amount.append(item[2])
    date = list(date)
    date.sort()
    for item in date:
        movie_count.append(amount.count(item))
    plt.rc('font', family='SimHei', size=12)
    plt.bar(date, movie_count, width=0.3, label="本年度拍摄电影数量", fc='r')
    plt.xlabel('年份')
    plt.ylabel = ('作品数量')
    plt.title("拍摄电影数量与年份的柱状图")
    plt.legend()
    plt.show()
    return True


def prize_amount_show(star):
    amount = []
    date = set()
    prize_count = []
    for item in star.reward:
        date.add(item[2])
        amount.append(item[2])
    date = list(date)
    date.sort()
    for item in date:
        prize_count.append(amount.count(item))
    plt.pie(prize_count, labels=date, autopct='%1.1f%%', startangle=90)
    plt.show()
    plt.close()
    return True


def save_information(star):
    name = star.name + "资料.xls"
    book = xlsxwriter.Workbook(name)
    sheet = book.add_worksheet('demo')
    sheet.write(0, 0, "基本信息")
    information_length = len(star.Information)
    count = 2
    sheet.write(1, 0, star.Base_Information)
    for i in range(information_length):
        sheet.write(count, 0, star.Information[i][0])
        sheet.write(count, 1, star.Information[i][1])
        count += 1
    book.close()


def save_movie(star):
    name = star.name + "主要作品.xls"
    book = xlsxwriter.Workbook(name)
    sheet = book.add_worksheet('demo')
    sheet.write(0, 0, "主要作品")
    count = 1
    for j in range(len(star.Data)):
        sheet.write(count, 0, star.Data[j][0])
        sheet.write(count, 1, star.Data[j][1])
        count += 1
    book.close()


def save_reward(star):
    name = star.name + "获奖资料.xls"
    book = xlsxwriter.Workbook(name)
    sheet = book.add_worksheet('demo')
    sheet.write(0, 0, "主要奖项")
    count = 1
    for k in range(len(star.reward)):
        sheet.write(count, 0, star.reward[k][0])
        sheet.write(count, 1, star.reward[k][1])
        count += 1
    book.close()
    return True


star = Star()


class MainFrame(wx.Frame):
    def __init__(self, parent, id, tittle):
        wx.Frame.__init__(self, parent, id, tittle, size=(800, 400))
        # 定义状态栏
        sb = self.CreateStatusBar(2)
        self.SetStatusWidths([-1, -2])  # 比例是1:2
        self.SetStatusText("Ready", 0)
        # 显示系统时间
        self.timer = wx.PyTimer(self.Notify)
        self.timer.Start(1000, wx.TIMER_CONTINUOUS)
        self.Notify()

    def InitUI(self):
        wx.StaticText(self, label="Name", pos=(20, 30))
        self._usermname = wx.TextCtrl(self, pos=(80, 20), size=(200, 40))
        self.submit_btn = wx.Button(self, label=u"提交", pos=(300, 20), size=(100, 40))
        self.Bind(wx.EVT_BUTTON, self.OnClick, self.submit_btn)

        wx.StaticText(self, label="输入照片数量", pos=(220, 90))
        self._number = wx.TextCtrl(self, pos=(300, 80), size=(100, 40))
        self.submit_number = wx.Button(self, label=u"获得图片", pos=(420, 80), size=(100, 40))
        self.Bind(wx.EVT_BUTTON, self.OnClick, self.submit_number)

        self.GetInformation = wx.Button(self, label=u"获得资料", pos=(20, 80), size=(100, 40))
        self.Bind(wx.EVT_BUTTON, self.OnClick, self.GetInformation)

        self.GetMovie = wx.Button(self, label=u"获得作品信息", pos=(20, 170), size=(100, 40))
        self.Bind(wx.EVT_BUTTON, self.OnClick, self.GetMovie)

        self.Get_reaward = wx.Button(self, label=u"获奖信息", pos=(300, 170), size=(100, 40))
        self.Bind(wx.EVT_BUTTON, self.OnClick, self.Get_reaward)

        self.show_prize_amount = wx.Button(self, label=u"生成饼图", pos=(20, 260), size=(100, 40))
        self.Bind(wx.EVT_BUTTON, self.OnClick, self.show_prize_amount)

        self.show_movie_amount = wx.Button(self, label=u"生成柱状图", pos=(300, 260), size=(100, 40))
        self.Bind(wx.EVT_BUTTON, self.OnClick, self.show_movie_amount)

    def Getname(self):
        return self._usermname.GetValue()

    def Getnumber(self):
        return self._number.GetValue()

    def OnClick(self, event):
        if event.GetEventObject() == self.submit_btn:
            star.name = self.Getname()
            print("Information of {} has been gotten".format(star.name))

        if event.GetEventObject() == self.GetInformation:
            Get_information(Get_html_data(Get_base_url(star.name)), star)
            save_information(star)
            print("Information of {} has been obtained".format(star.name))

        if event.GetEventObject() == self.submit_number:
            number = self.Getnumber()
            print(number)
            baidu = BaiDu_picture(star.name, 1, number)
            baidu.queryset()
            print("pictures of {} have been obtained".format(star.name))

        if event.GetEventObject() == self.GetMovie:
            Get_movie(Get_html_data(Get_base_url(star.name)), star)
            save_movie(star)
            print("Movie information of {} has been obtained".format(star.name))

        if event.GetEventObject() == self.Get_reaward:
            Get_reward(Get_html_data(Get_base_url(star.name)), star)
            save_reward(star)
            print("Reward information of {} has been obtained".format(star.name))

        if event.GetEventObject() == self.show_movie_amount:
            movie_amount_show(star)

        if event.GetEventObject() == self.show_prize_amount:
            prize_amount_show(star)

    def Notify(self):
        t = time.localtime()
        st = time.strftime('%Y-%m-%d    %H:%M:%S', t)
        self.SetStatusText(st, 1)


class App(wx.App):
    def __init__(self):
        super(self.__class__, self).__init__()

    def OnInit(self):
        self.tittle = "百度爬虫,帮你批量获取信息"
        frame = MainFrame(None, -1, self.tittle)
        frame.Show(True)
        frame.InitUI()
        return True


def main():
    if __name__ == "__main__":
        app = App()
        app.MainLoop()


main()

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值