logo_2024
萌の领域

【技术】python爬虫教程(1)

技术教程 pengpengf - 8

打算写点爬虫的教程,用几个例子告诉大家怎样用爬虫爬取资源。

一.需要的软件

1.Python

爬虫主要使用的语言,因为编写起来很简单。

安装可以参考https://blog.csdn.net/nmjuzi/article/details/79075736

注意下载python3系列的,一般选择最新的就行。

2.VScode

VScode是一款好用的编辑器,我用的很喜欢。

下载安装之后,在vscode中安装Python支持,一般步骤是Ctrl+Shift+X快捷键,然后在左边搜索框里输入Python,然后安装名字叫Python的插件。如果显示网络问题就刷新。

3.火狐浏览器和谷歌浏览器

两个浏览器都比较方便,火狐浏览器方便对网页进行分析。而谷歌浏览器是因为加载动态网页需要它。

4.几个python库

主要有urllib、json、os、time(安装python时自带),requests、bs4、selenium(可能需要安装)。

安装库方法如果不懂的可以百度。同时selenium库需要额外的控制程序,需要添加火狐或者谷歌浏览器的驱动,我选择了谷歌浏览器,当然两个一起也没有问题。

不懂看教程https://www.cnblogs.com/michael-cheng/p/6885705.html

5.ffmpeg

下载地址:https://ffmpeg.org/

主要是需要一个叫做ffmpeg.exe的程序。

主要用于视频、图像处理。

二.第一个示例

首先,https://lol.qq.com/data/info-heros.shtml这个是英雄联盟游戏英雄资料界面,就不截图了,自己点开看,尽量用火狐打开。

https://lol.qq.com/data/info-defail.shtml?id=1 

这个是第一个英雄的资料,而我的目的是把这个英雄所有皮肤的海报图片下载下来。

当然,鼠标右键另存为就可以下载下来。

但是,我想要做的是下载所有英雄的所有皮肤。

这个就是这个示例要完成的功能。

那我们的程序设计也很简单:

第1步,获取英雄资料列表

第2步,对每一个英雄的资料获取皮肤信息

第2.1步,对每一个皮肤下载并保存到本地

写成python程序就应该是这样的

英雄列表=获取英雄列表(‘https://lol.qq.com/data/info-heros.shtml’)
for 英雄 in 英雄列表:
    皮肤列表=获取皮肤列表(英雄)
    for 皮肤 in 皮肤列表:
        下载皮肤图片(皮肤)
 
看起来不是很难对不对。
首先我们实现第一个功能根据地址获取英雄列表。
我们使用火狐浏览器的右键检查元素功能,把鼠标移到第一个英雄的上面,然后右键检查元素。

而我们可以看到蓝色行上面的两行的info-defail.shtml?id=1就是这个英雄的资料的地址的后缀对不对。回去看地址https://lol.qq.com/data/info-defail.shtml?id=1 。

而我们看到这个后缀是属于a这个元素的叫href的属性的值,a又是属于这个叫li的元素。下面还有很多个li元素,点开第二个li元素就发现信息是英雄奥拉夫的。我们知道了这个一堆li记录了英雄资料,而这些li从属于上面这个id叫做jSearchHeroDiv的ui元素的。而在网页中id是唯一的,也就是说我们可以用jSearchHeroDiv来找到这个元素。
上代码
需要用到两个库,所以在文件开头添加:
from bs4 import BeautifulSoup
from urllib import request
然后是功能函数
 
def 获取英雄列表(地址):
    英雄列表网页=request.Request(地址)
    网页代码 = request.urlopen(英雄列表网页).read()
    分析器 = BeautifulSoup(网页代码, ‘html.parser’)
    查找结果 = 分析器.find(id=”jSearchHeroDiv”)
    print(查找结果)
 
运行后得到结果:
<ul class=”imgtextlist” id=”jSearchHeroDiv”>
<li>拼命加载中</li>
<!– <li class=”current”><a href=”#”><img src=”//game.gtimg.cn/images/lol/web201310/101/tmp/tmp-user.jpg” alt=””><p>稻草人</p><span class=”sbg”><i class=”commspr commico-search”></i></span></a></li> –>
</ul>
发现元素是这个元素,但是‘拼命加载中’说明这些信息是异步加载的,就是说浏览器根据代码在运行过程中从服务器获取的,并不是一开始就写在这个网页的描述文件上的。而我们使用的request只是获取这个描述文件,没办法运行上面的代码。
 
那怎么办呢?
这个问题有两个解决办法。
1.使用selenium控制浏览器打开这个网页,加载好再分析
2.寻找异步加载的数据
 
先看第一种
需要添加导入信息:
from selenium import webdriver
import time
 
def 获取英雄列表(地址):
    浏览器=webdriver.chrome.webdriver.WebDriver()
    英雄列表网页=浏览器.get(地址)
    查找结果 = 浏览器.find_element_by_id(‘jSearchHeroDiv’).find_elements_by_tag_name(‘li’)
    for li in 查找结果:
        print(li.find_element_by_tag_name(‘a’).get_attribute(‘href’))
    浏览器.close()
部分运行结果是:
https://lol.qq.com/data/info-defail.shtml?id=1
https://lol.qq.com/data/info-defail.shtml?id=2
https://lol.qq.com/data/info-defail.shtml?id=3
https://lol.qq.com/data/info-defail.shtml?id=4
https://lol.qq.com/data/info-defail.shtml?id=5
https://lol.qq.com/data/info-defail.shtml?id=6
https://lol.qq.com/data/info-defail.shtml?id=7
 
这个就对了。
 
第二种方法
回到火狐浏览器,把代码模板的模块转到最上面的网络模块。
然后刷新网页,就可以看到在网页刷新加载过程中浏览器向服务器获取的所有数据。

发现浏览器加载了很多个文件,不着急,先看看这些文件的名字。最终,我找到了一个叫做hero_list.js的文件,就是英语再差也应该知道这是英雄列表的意思,点开。

这不就是我想要的结果吗?

根据消息头get的地址,可以写代码了。
def 获取英雄列表(地址):
    响应=request.Request(地址)
    代码 = request.urlopen(响应).read()
    print(代码)
获取英雄列表(‘https://game.gtimg.cn/images/lol/act/img/js/heroList/hero_list.js’)
部分结果为:
b'{“hero”:[{“heroId”:”1″,”name”:”\u9ed1\u6697\u4e4b\u5973″,”alias”:”Annie”,”title”:”\u5b89\u59ae”,”roles”:[“mage”],”isWeekFree”:”0″,”attack”:”2″,”defense”:”3″,”magic”:”10″,”difficulty”:”6″,”selectAudio”:”https:\/\/game.gtimg.cn\/images\/lol\/act\/img\/vo\/choose\/1.ogg”,”banAudio”:”https:\/\/game.gtimg.cn\/images\/lol\/act\/img\/vo\/ban\/1.ogg”,”isARAMweekfree”:”0″,”ispermanentweekfree”:”0″,”changeLabel”:”\u6539\u52a8\u82f1\u96c4″,”goldPrice”:”4800″,”couponPrice”:”2000″,”camp”:””,”campId”:””,”keywords”:”\u5b89\u59ae,\u9ed1\u6697\u4e4b\u5973,\u706b\u5973,Annie,anni,heianzhinv,huonv,an,hazn,hn”},
 
编码有些不同,没关系,这都是小事。
但是这个输出里并没有网页地址,所以我们用
 
最后写成代码:
def 获取英雄列表(地址):
    浏览器=webdriver.chrome.webdriver.WebDriver()
    英雄列表网页=浏览器.get(地址)
    查找结果 = 浏览器.find_element_by_id(‘jSearchHeroDiv’).find_elements_by_tag_name(‘li’)
    英雄列表=[li.find_element_by_tag_name(‘a’).get_attribute(‘href’) for li in 查找结果]
    浏览器.close()
    return 英雄列表
 
def 获取英雄列表(地址):
    响应=request.Request(地址)
    代码=request.urlopen(响应).read().decode(‘UTF-8′,’ignore’)
    json列表=json.loads(代码)[‘hero’]
    英雄列表=[‘https://lol.qq.com/data/info-defail.shtml?id={}’.format(英雄[‘heroId’]) for 英雄 in json列表]
    return 英雄列表
接下来是获取皮肤列表这个功能,我们打开https://lol.qq.com/data/info-defail.shtml?id=1进行分析。
查看代码发现:

只有原画的,不过这张图片的地址倒是获取到了。

当我点击查看第一个皮肤的时候,代码发生了变化。

那些皮肤居然出现了,这说明这些信息也是异步加载的。

同样的,两个方法。
1.控制浏览器打开,然后让浏览器自动点击一下,然后再获取信息
2.寻找这些信息
刚才的功能如果尝试了就知道,控制浏览器花费的时间和性能都很高,所以就不说第一个方法了,不是我不会,而是真的时间太长了,用这种方法爬一次得两小时。
同样的,网络模块刷新网页,最终发现这些信息在一个叫1.js的文件里

点开之后就可以看到有一个叫mainimg的属性https://game.gtimg.cn/images/lol/act/img/skin/big1000.jpg

这个就是我们要找的图片的地址。
而它的请求地址是https://game.gtimg.cn/images/lol/act/img/js/hero/1.js
那我猜测,因为这个英雄的id是1所以叫1.js,那英雄id是2是不是就是2.js。
打开第二个英雄的网页,发现果然是2.js。
所以我们第一步获取的heroId属性加上前缀就是我们想要的地址。
然后再获取每一个皮肤的mainimg属性来下载就行了。
写到这我也不想写了,直接给代码吧,有兴趣的自己研究,怎么找图片已经描述完了,终于具体代码实现,有编程基础的人都应该很容易实现。
 
import urllib.request
import json
import os
def downloadimg(imgurl,name,filepath):
    if not os.path.exists(filepath):
        print(‘正在下载创建文件夹’+filepath)
        os.makedirs(filepath)
    filename = ‘{}{}.jpg’.format(filepath, name)
    if not os.path.exists(filename):
        print(‘正在下载:{}’.format(name))
        try:
            urllib.request.urlretrieve(imgurl, filename=filename)
        except:
            print(‘{}下载失败’.format(name))
savePathAll=’D:/英雄联盟皮肤’
if not os.path.exists(savePathAll):
    os.makedirs(savePathAll)
url=’https://game.gtimg.cn/images/lol/act/img/js/heroList/hero_list.js’
page = urllib.request.Request(url)
html = urllib.request.urlopen(page).read().decode(‘UTF-8′,’ignore’)
hero_list=json.loads(html)[‘hero’]
for hero in hero_list:
    heroid=hero[‘heroId’]
    heroname=hero[‘name’]
    print(‘正在下载{} {}的皮肤’.format(heroname,hero[‘title’]))
    header=’https://game.gtimg.cn/images/lol/act/img/js/hero/{}.js’.format(heroid)
    savePath=savePathAll+’/{}/’.format(heroname)
    response = urllib.request.Request(header)
    html = urllib.request.urlopen(response).read().decode(‘UTF-8′,’ignore’)
    skins=json.loads(html)[‘skins’]
    for skin in skins:
        skinName=skin[‘name’]
        skinName=skinName.replace(‘/’,”)
        downloadurl=skin[‘mainImg’]
        if downloadurl==”:
            continue
        downloadimg(downloadurl,skinName,savePath)

下一次我会发在两个网站上爬黄书的例子。

  • 萌の领域是一个和谐有爱的ACG文化交流圈,这里是众多二次元文化爱好者的集结地。
  • 本文章是由 萌の领域 会员 pengpengf 的创作作品。
  • 转载文章时请保留原出处,资源请重新打包!并且附上完整的地址:https://www.moezone.dev/175709.html
  • 资源分享不易,有时间的萌友可以重新打包上传一份,发链接到评论区接力分享,薪火相传呢~
  • 如资源链接失效,请先查看是否是两个星期之前的资源,超过时间默认不补档,请考虑是否要点击下载。其他情况请点击上方举报,等待管理员处理。
  • 下载之前请查看评论区,如果有人提示资源已失效请不要点击下载浪费萌币,也不要说作者骗币,下载消耗的萌币是被服务器回收了。

© 2019 - 2024 💝 Www.MoeZone.Dev