您的位置:首页 > 编程语言 > Python开发

Requests+Beautifulsoup+re百度贴吧抓取实例(python3.4逐行解释)

2015-10-21 08:40 549 查看
__author__ = 'http://www.yeayee.com/'
# -*- coding: utf-8 -*-
# 导入requests模块
import requests
# 导入re正则模块
import re
# 导入soup模块
from bs4 import BeautifulSoup
# 导入time模块
import time
#定义一个爬虫类,此次目标是该帖“http://tieba.baidu.com/p/3805717173?pn=”中的通知书,单线程
class Admission:
    # 定义一个协议头,我用的是Httpwatch,也可以用firebug或者fiddler等监测工具
    headers = {'User-Agent':u'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; .NET4.0C; .NET4.0E)'}#这是请求头
    #恩,下面的网址本次要采集的帖子,=后面为贴吧页码
    baseURL = 'http://tieba.baidu.com/p/3805717173?pn='

     #获取贴吧页面数,截至2015.10.20日该贴有26页
    def getPageNum(self):
        #获取帖子页数的正则表达式,页码数在第一页就能找到,当然每页都有,需要对采集网站的代码结构有个初步的了解,知己知彼
        url = self.baseURL +str(1)
        # 获取Url的源码,最开始已经定义代码格式Utf-8,百度有时候还会是GBK,分析不同的网站不同滴
        htmltext = requests.get(url,headers=self.headers).text
        #接下来正则匹配,记忆中万能的匹配格式是.*?或者(.*?)
        pattern = re.compile('max-page="(.+?)" type="text"')
        # 因为唯一,所以直接将页面数转化为int格式,因为采集到的是字符串
        result = int(re.findall(pattern,str(htmltext))[0])
        #返回准备采集的页面数,供下一步调用
        return result

     #取得所有通知书的地址
    def getURL(self,numpage):
        # 定义一个空白数列,准备用来存放照片的网址
        realalllinks = []
        # 定义一个循环,准备从第一页采集到最后一页,采集目标为各页图片的地址
        for num in range(0,(numpage+1)):
            # 生成即将采集的地址
            url = self.baseURL +str(num)
            # 生成采集网址对应网页的源码
            htmltext = requests.get(url,headers=self.headers).text
            # 终于用到soup了,其实正则也是可以的,不过不知道为什么BS4要增加"html.parser",之前的例子是木有的
            Soup = BeautifulSoup(htmltext, "html.parser")
            #获取通知书地址,这个网址只是真实网址的一部分后缀
            admissions = Soup.find_all('img',class_='BDE_Image')
            alllinks = []
            # 生成alllinks数列的成员,也就是照片的网址,而each是admissions数列的成员。
            for each in admissions:
                eachlink = each.get('src')
                # 向alllinks中添加新的单个地址
                alllinks.append(eachlink)
            # 延迟5毫秒
            time.sleep(5)
            # 把生成的alllinks直接扩展进realalllinks列表
            realalllinks.extend(alllinks)
        # 返回扩展后的连接列表,该类第一步就是要先采集完所有的网址,接下来才是保存图片,随后再改写一个单独的实时采集方案
        return realalllinks

#保存图片
    def saveImage(self,imgUrls):
        # 获取图片地址链接的数量
        lenimages = len(imgUrls)
        # 先自行手动创建一个文件夹用来保存采集的图片
        DstDir="D:\\通知书\\"
        # 采集并保存图片
        for imageNum in range(lenimages):
            # 生成一个图片名称
            imageName = str(imageNum)+'.jpg'
            # 提取图片的地址
            imageurl = imgUrls[imageNum]
            # requests请求
            response = requests.get(imageurl, stream=True)
            # 获取请求内容
            image = response.content
            # 保存图片的路径
            realname = DstDir+imageName
            # 读写数据保存图片
            try:
                with open(realname,"wb") as jpg:
                    jpg.write(image)
            except IOError:
                print("IO Error\n")
            finally:
                # 关闭图片读写
                jpg.close
            # 再来一个延迟
            time.sleep(1)
# __author__ = 'http://www.yeayee.com/'
# 实例化类
ad = Admission()
# 获取页码数量
pagenum = ad.getPageNum()
print (pagenum)
# 获取图片的地址
allurl = ad.getURL(pagenum)
# 保存图片
ad.saveImage(allurl) #下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: