寒假里的python简单爬虫实践

寒假在家无事可干,翻微博看到了EASY前辈说的一句话

程序员应该在过年期间写一个只为自己的程序

深以为然,于是开始思索我目前的技术力能够为自己写啥东西,未果。

又是在刷微博的时候,发现自己收藏里全是一堆小偶像的图片,为什么在收藏里呢,因为平时实在是懒的一张一张去保存,只能放在收藏中。然而一直放在收藏里显然也不是个事,这时想到,我可以用python写个爬虫,把微博上的图片爬取下来。

 需求:通过python实现爬虫,用户输入内容,爬虫爬取在微博搜索此内容后搜索页的图片。

开始。

一个小爬虫的话肯定得有访问、处理、获取这几步,引入request库用作访问,bs4用作内容处理

考虑到要用正则表达式,引入re.compile

考虑到要往本地保存图片,引入os和shutil

# -*- coding:utf-8 -*-
# powered by Midorii
# release date:19.2.4
import requests
from bs4 import BeautifulSoup
import re
import os
import shutil
import time
import datetime

下面开始研究微博搜索界面的代码。通过查阅相关博客得知weibo.com因为JS应用较多,难以简单爬取,那该怎么办呢。
继续查找资料,得知了微博的低流量入口weibo.cn仍在运作,即该页面。

查看源代码后发现该网站源代码完全裸露,适合爬取。

如图所示,图片链接为裸露的.jpg格式,因此决定weibo.cn为突破口。
观察搜索界面的url格式

可以发现,“keyword=”后面即为搜索内容,“page=”后为页码。注意此处的汉字是chrome优化后结果,实际应为

https://weibo.cn/search/mblog?hideSearchFrame=&keyword=%E5%A0%80%E6%9C%AA%E5%A4%AE%E5%A5%88&page=2

汉字被处理为编码。为了对汉字进行处理,引入urillib

import urllib.parse

编写输入搜索内容和页码范围的函数

# 获取输入信息
def get_search_value():
    searchVal = input("搜索条目:")
    return urllib.parse.quote(searchVal)


# 获取页码,返回处理后的列表
def get_page_number():
    startPage = int(input("起始页码:"))
    endPage = int(input("结束页码:"))
    return range(startPage,endPage+1)

考虑到微博需要使用cookies,编写相关函数。

# 读入本地cookie
def read_cookie():
    localCookiePath = os.getcwd()+"\cookie.txt"
    print(f"尝试自{localCookiePath}读入cookie")
    if os.path.exists(localCookiePath) is False:
        print("未检测到本地cookie")
        tempCookies = input("请输入微博登录时的cookies:")
    else:
        print("本地cookie读入成功")
        with open(localCookiePath, 'r') as cookiesFile:
            tempCookies = cookiesFile.read()
    dictCookie={"Cookie": tempCookies}
    print(f"使用cookie:{tempCookies}")
    return dictCookie


# 保存有效cookie
def save_cookie(tempCookies):
    with open(os.getcwd()+"\cookie.txt",'w') as cookiesFile:
        cookiesFile.write(tempCookies)

在实际使用中,发现cookie失效时会自动跳转至登录页面,登录页面中存在名为“loginAcion”的元素,以此特性实现cookie的检验。

# 检验cookie是否有效
def check_cookie(soup,cookies):
    check = []
    check = soup.find_all('a', id=re.compile("loginAction"))
    if check:
        print("cookies无效,请检查")
        os.remove(os.getcwd() + "\cookie.txt")
        os.system("pause")
        quit()
    else:
        save_cookie(cookies['Cookie'])

下面开始正式的爬取

通过观察微博界面,可知weibo.cn的图片当超过一张时,会形成“组图”超链接,“组图”的超链接含有picAll字段,以此为突破口获取组图url

# 获取网页源代码,返回图片地址列表
def get_anl_site(pages, searchVal, cookies):
    imgUrlList=[]
    #生成路径
    for page in pages:
        print(f"正在获取第{page}页到第{pages[-1]}页的内容")
        url = "https://weibo.cn/search/mblog?hideSearchFrame=&keyword=" + searchVal + "&page=" + str(
            page)
        print(f"生成路径{url}")
        #防止访问过频繁
        time.sleep(5)
        #生成BS对象并处理源代码
        r = requests.get(url, cookies=cookies)
        soup = BeautifulSoup(r.text, "lxml")
        #检验cookie
        check_cookie(soup,cookies)
        #保存该页面全部组图url
        imgList = soup.find_all('a', href=re.compile("picAll"))
        #通过访问保存的组图url,获取组图中全部图片的url,观察可知组图缩略图均含有thumb字段,以此为突破口保存图片url
        for result in imgList:
            albumLink = result.get("href")
            imgr = requests.get(albumLink, cookies=cookies)
            imgSoup = BeautifulSoup(imgr.text, "lxml")
            linkList = imgSoup.find_all('img', src=re.compile("thumb"))
            #print(linkList)
            #通过观察缩略图和大图url差别可发现二者的不同之处是缩略图的thumb180字段在大图时为large,通过替换实现保存大图
            for link in linkList:
                link = link.get("src")
                link = link.replace("thumb180", "large")
                #将处理好的url保存至列表imgUrlList
                imgUrlList.append(link)
            #print(imgUrlList)
        #保存单图,wap180为单图特有字段
        imgSingle = soup.find_all('img', src=re.compile("wap180"))
        for link in imgSingle:
            link = link.get("src")
            #同样进行更换处理
            link = link.replace("wap180", "large")
            imgUrlList.append(link)
        #print(imgUrlList)
    print("有效cookie已储存至本地")
    print(f"图片爬取完成,共获取图片地址{len(imgUrlList)}个")
    #对图片Url进行去重
    imgUrlListRefine = list(set(imgUrlList))
    imgUrlListRefine.sort(key=imgUrlList.index)
    print(f"简单去重后共获取图片地址{len(imgUrlListRefine)}个")
    return imgUrlListRefine

保存图片

# 保存图片
def img_download(imgUrlList):
    tempPath = input("输入存储图片文件夹名,留空则默认以当前时间为文件夹名:")
    if tempPath.strip() == '':
        tempPath = str(datetime.datetime.now())
        tempPath = tempPath.replace(':', '')
        tempPath = tempPath.replace(" ", '')

    imgPath = os.getcwd() + "/" + tempPath
    if os.path.exists(imgPath) is False:
        os.mkdir(imgPath)
    x = 1
    for imgUrl in imgUrlList:
        temp = imgPath + '/' + str(x) + imgUrl[-4:]
        print(f"正在下载第{x}张图片")
        print(f"图片url为{imgUrl}")
        try:
            r = requests.get(imgUrl, stream=True)
            if r.status_code == 200:
                with open(temp, 'wb') as f:
                    r.raw.decode_content = True
                    shutil.copyfileobj(r.raw, f)
                    x += 1
        except:
            print(f"该图片下载失败{imgUrl}")

    print(f"图片下载完成,一共下载了{x - 1}张图片")

编写入口

if __name__ == '__main__':
    cookie=read_cookie()
    searchVal = get_search_value()
    pages = get_page_number()
    imgUrlList = get_anl_site(pages, searchVal,cookie)
    img_download(imgUrlList)
    os.system("pause")

以上,一个简单的爬虫就编写好了

进行测试

基本满足要求。

全部源代码如下

# -*- coding:utf-8 -*-
# powered by Midorii
# release date:19.2.4
import requests
from bs4 import BeautifulSoup
import re
import os
import shutil
import urllib.parse
import time
import datetime


# 读入本地cookie
def read_cookie():
    localCookiePath = os.getcwd()+"\cookie.txt"
    print(f"尝试自{localCookiePath}读入cookie")
    if os.path.exists(localCookiePath) is False:
        print("未检测到本地cookie")
        tempCookies = input("请输入微博登录时的cookies:")
    else:
        print("本地cookie读入成功")
        with open(localCookiePath, 'r') as cookiesFile:
            tempCookies = cookiesFile.read()
    dictCookie={"Cookie": tempCookies}
    print(f"使用cookie:{tempCookies}")
    return dictCookie


# 保存有效cookie
def save_cookie(tempCookies):
    with open(os.getcwd()+"\cookie.txt",'w') as cookiesFile:
        cookiesFile.write(tempCookies)


# 检验cookie是否有效
def check_cookie(soup,cookies):
    check = []
    check = soup.find_all('a', id=re.compile("loginAction"))
    if check:
        print("cookies无效,请检查")
        os.remove(os.getcwd() + "\cookie.txt")
        os.system("pause")
        quit()
    else:
        save_cookie(cookies['Cookie'])


# 获取输入信息
def get_search_value():
    searchVal = input("搜索条目:")
    return urllib.parse.quote(searchVal)


# 获取页码,返回处理后的列表
def get_page_number():
    startPage = int(input("起始页码:"))
    endPage = int(input("结束页码:"))
    return range(startPage,endPage+1)


# 获取网页源代码,返回图片地址列表
def get_anl_site(pages, searchVal, cookies):
    imgUrlList=[]
    #生成路径
    for page in pages:
        print(f"正在获取第{page}页到第{pages[-1]}页的内容")
        url = "https://weibo.cn/search/mblog?hideSearchFrame=&keyword=" + searchVal + "&page=" + str(
            page)
        print(f"生成路径{url}")
        #防止访问过频繁
        time.sleep(5)
        #生成BS对象并处理源代码
        r = requests.get(url, cookies=cookies)
        soup = BeautifulSoup(r.text, "lxml")
        #检验cookie
        check_cookie(soup,cookies)
        #保存该页面全部组图url
        imgList = soup.find_all('a', href=re.compile("picAll"))
        #通过访问保存的组图url,获取组图中全部图片的url,观察可知组图缩略图均含有thumb字段,以此为突破口保存图片url
        for result in imgList:
            albumLink = result.get("href")
            imgr = requests.get(albumLink, cookies=cookies)
            imgSoup = BeautifulSoup(imgr.text, "lxml")
            linkList = imgSoup.find_all('img', src=re.compile("thumb"))
            #print(linkList)
            #通过观察缩略图和大图url差别可发现二者的不同之处是缩略图的thumb180字段在大图时为large,通过替换实现保存大图
            for link in linkList:
                link = link.get("src")
                link = link.replace("thumb180", "large")
                #将处理好的url保存至列表imgUrlList
                imgUrlList.append(link)
            #print(imgUrlList)
        #保存单图,wap180为单图特有字段
        imgSingle = soup.find_all('img', src=re.compile("wap180"))
        for link in imgSingle:
            link = link.get("src")
            #同样进行更换处理
            link = link.replace("wap180", "large")
            imgUrlList.append(link)
        #print(imgUrlList)
    print("有效cookie已储存至本地")
    print(f"图片爬取完成,共获取图片地址{len(imgUrlList)}个")
    #对图片Url进行去重
    imgUrlListRefine = list(set(imgUrlList))
    imgUrlListRefine.sort(key=imgUrlList.index)
    print(f"简单去重后共获取图片地址{len(imgUrlListRefine)}个")
    return imgUrlListRefine


# 保存图片
def img_download(imgUrlList):
    tempPath = input("输入存储图片文件夹名,留空则默认以当前时间为文件夹名:")
    if tempPath.strip() == '':
        tempPath = str(datetime.datetime.now())
        tempPath = tempPath.replace(':', '')
        tempPath = tempPath.replace(" ", '')

    imgPath = os.getcwd() + "/" + tempPath
    if os.path.exists(imgPath) is False:
        os.mkdir(imgPath)
    x = 1
    for imgUrl in imgUrlList:
        temp = imgPath + '/' + str(x) + imgUrl[-4:]
        print(f"正在下载第{x}张图片")
        print(f"图片url为{imgUrl}")
        try:
            r = requests.get(imgUrl, stream=True)
            if r.status_code == 200:
                with open(temp, 'wb') as f:
                    r.raw.decode_content = True
                    shutil.copyfileobj(r.raw, f)
                    x += 1
        except:
            print(f"该图片下载失败{imgUrl}")

    print(f"图片下载完成,一共下载了{x - 1}张图片")


if __name__ == '__main__':
    cookie=read_cookie()
    searchVal = get_search_value()
    pages = get_page_number()
    imgUrlList = get_anl_site(pages, searchVal,cookie)
    img_download(imgUrlList)
    os.system("pause")

目前的不足之处:

没找到爬取超级话题的方法。

cookie存在失效问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值