• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
heremei
博客园    首页    新随笔    联系   管理    订阅  订阅
【Heremei】Python爬虫个人学习笔记-1-记第一次爬虫学习

老父亲让我帮忙下载个微信公众号的音频
image
具体而言就是下下来这个页面上列表里所有的音频文件:https://mp.weixin.qq.com/mp/homepage?__biz=MzA4NzMzMjczMg==&hid=9&sn=fe1ec70d80401265f5c7018120879a63&scene=18&uin=&key=&devicetype=Windows+10+x64&version=6302019a&lang=zh_CN&ascene=7&fontgear=2

需要读者:学会基本的python编程

很遗憾到最后还是决定不按照时间顺序来写,那样脉络太不清晰了,不然我是很想记录我是怎么遇到其中的每一个问题的。

以下源码:

from selenium import webdriver
import time
from selenium.webdriver.common.keys import Keys
import requests as rq

if __name__=='__main__':
    driver=webdriver.Firefox()
    base_url='https://mp.weixin.qq.com/mp/homepage?__biz=MzA4NzMzMjczMg==&hid=11&sn=bb7bc45d8a49ff0607153db985d2c2c2&scene=18&uin=&key=&devicetype=Windows+10+x64&version=6302019a&lang=zh_CN&ascene=7&fontgear=2'
    driver.get(base_url)
   # time.sleep(3)

    for i in range(1,10):
        js="var q=document.documentElement.scrollTop=10000"
        driver.execute_script(js)
        time.sleep(1)
    eles=driver.find_elements_by_class_name('list_item')

    num=0
    href=[None]

    for ele in eles:
        href.append(ele.get_attribute('href'))
        num+=1
        
    for i in range(1,num+1):
        driver.get(href[i])
        all_handles = driver.window_handles
        new_handle = all_handles[-1]
        driver.switch_to.window(new_handle)
        time.sleep(3)
        a=driver.find_elements_by_class_name('weui-audio-btn')
        a[-1].click()
        au=driver.find_element_by_tag_name('audio')
        title=driver.title
        h=au.get_attribute('src')
        print(title)
        filepath='D:'+'\\'+title+'.mp3'
        open(filepath, 'wb').write(rq.get(h).content)
        

Part 1 初识Splinter

一开始老父亲发了个链接
https://blog.csdn.net/lpwmm/article/details/108722225

这个博主用的是Splinter,所以一开始我打算用Splinter。
Splinter是Python一个操作浏览器的包,但其实是基于Selenium来实现的。有人说这东西更简便,经过后来的研究我反正没看出来。Splinter最大的问题在于用的人少,网上很少能找到相关的资料,所以最终没有选择它。

这篇微博最大的优点在于他和我要爬的都是微信公众号,有极大的相似点,所以后面借鉴了很多。

Part 2 点亮前置技能:HTML

其实Web编程主要就是HTML,CSS,JavaScript
一个网页本质上还是一个文档。HTML告诉我们这个文档里有什么东西;CSS规定了这个文档里文字等内容的样式,就是怎么显示,字体、颜色之类;JavaScript是写在文档里的程序,负责组织人机交互之类的,其实就是响应。

在本次任务中,基本不涉及CSS和JavaScript,只需要了解HTML就好。具体参见runoob.com(菜鸟教程)和www.w3school.com.cn,以下附上链接:
菜鸟教程:https://www.runoob.com/html/html-tutorial.html
w3school:https://www.w3school.com.cn/h.asp

只需要知道这个网页大概是如何运作的就好,不需要了解那么多,尤其是很多细节并不需要。

Part 3 分析任务

我们的任务其实就是两部分:①寻找到真正的音频地址 ②下载
其中第①部分是大头,②只需要调用一下函数就能解决

我们分析一下①任务:
我们的原始url是:
https://mp.weixin.qq.com/mp/homepage?__biz=MzA4NzMzMjczMg==&hid=9&sn=fe1ec70d80401265f5c7018120879a63&scene=18&uin=&key=&devicetype=Windows+10+x64&version=6302019a&lang=zh_CN&ascene=7&fontgear=2

我们要从这里一个一个打开里面内嵌的网址,然后从这些网址里:(这里举一个例子)https://mp.weixin.qq.com/s?__biz=MzA4NzMzMjczMg==&mid=2650878896&idx=2&sn=a2015a04ca0beae19baad45a86b73db0&scene=19#wechat_redirect 找到具体的音频文件下载。

从代码角度分析,我们需要实现两个功能:1 操作浏览器实现交互 2 从网页里提取我们需要的信息

Part 4 Selenium!Selenium!

Selenium可以说是很强大了,它是这次任务的核心。

一定要推荐一位博主的文章,写的很详细,是我最大的助力:
https://www.cnblogs.com/yoyoketang/tag/selenium/

Selenium - 安装

安装selenium

1 打开cmd

2 输入pip install selenium,回车

3 好的,看着他自动安装就好

(不得不说python这点太™方便了)

相关驱动:getodriver/chromedriver

selenium其实就是操控你的浏览器,你不同的浏览器有不同的类去实现。selenium 3 比起selenium 2 需要额外安装一个软件:对于firefox是getodriver.exe,对于chrome是chromedriver.exe。
我用的是firefox,所以底下都写firefox相关的了。chrome其实差不太多,我都会附各种链接,那些链接里提到chrome相关的事。
https://github.com/mozilla/geckodriver/releases/tag/v0.27.0
从这里可以下载getodriver,稍微有点慢,所以耐心等待。我没有找到国内的好的下载地址。
另外,请尽量保证你的getodriver是最新版,要不然可能会有bug,以下我会提到。
剩下的东西可以参考:https://www.cnblogs.com/yoyoketang/p/selenium.html

Selenium 基本操作

from selenium import webdriver是我们引用库
driver=webdriver.Firefox()创建一个driver对象
driver.get(url)访问url这个网址,url是一个str变量,例:`driver.get('www.baidu.com')

Selenium 切换页面

有的网页在driver.get()之后默认打开新标签页,但是我们selenium还停留在原来的标签页,所以需要我们切换过去

每一个网页都是一个handle句柄(我也不知道具体是啥,我理解成线程一样的东西)
我们有driver.switch_to.window(handle)来切换到handle对应的页面上(handle是一个str类型变量)

我们要知道新打开来的那个句柄是什么,采取这样的方法:

all_handles = driver.window_handles
new_handle = all_handles[-1]

new_handle就是我们找到的新打开的页面的句柄
我们首先用driver.window_handles返回一个列表,是所有的句柄。
句柄的最后一个元素就是新打开的了

参考网站:
https://www.cnblogs.com/jinbaobao/p/13901750.html
https://www.cnblogs.com/Chan94/p/9883352.html
https://www.cnblogs.com/yoyoketang/p/6128611.html

Selenium JS指令 - 滚动页面

我们的页面不是一次性显示出来的,很多网站(就比如这次我们要面对的)需要到最底部才会往下加载,所以我们需要让程序滚动到道最底部让他加载一下。

参考网址:https://www.cnblogs.com/yoyoketang/p/6128655.html

JS就是JavaScript,前文说过大致的作用,我们就是要让这个网页执行一个程序(做出响应)

具体我没有研究JS,只是抄了上面网址的方法:

滚动页面到底部:

js="var q=document.documentElement.scrollTop=10000"
driver.execute_script(js)

当然也可以使用键鼠事件,控制键盘点空格。具体其他的可以自己研究。

键鼠参考网址:https://www.cnblogs.com/yoyoketang/p/6128607.html

Selenium Profile配置文件更改

参考网址:https://www.cnblogs.com/yoyoketang/p/7657436.html

由于我很早就加上这个代码了,所以甚至不知道这个东西究竟需不需要,有兴趣的自己去看就好,不是重点。

而且后来写到最后我也给删了。

Selenium 定位元素 重点

参考网址:
https://www.cnblogs.com/yoyoketang/p/6123890.html(我们今天用到的不需要装他说的那些,因为不用XPath)
https://www.cnblogs.com/yoyoketang/p/6128599.html
https://www.cnblogs.com/yoyoketang/p/7153053.html

这是最重要的部分。经过简单的学习,我们知道网页都是由一个个元素组成。我们要找的链接当然也在元素里面。我们这部分要做的,就是F12观察页面的源代码,分析我们从哪里能找到我们要找的元素。

首先第一步我们找到页面里面每一条故事的地址。

这里定义一下称谓,最初的网址
https://mp.weixin.qq.com/mp/homepage?__biz=MzA4NzMzMjczMg==&hid=9&sn=fe1ec70d80401265f5c7018120879a63&scene=18&uin=&key=&devicetype=Windows+10+x64&version=6302019a&lang=zh_CN&ascene=7&fontgear=2
我们叫做首页

点进去以后的网址是:https://mp.weixin.qq.com/s?__biz=MzA4NzMzMjczMg==&mid=2650878896&idx=2&sn=a2015a04ca0beae19baad45a86b73db0&scene=19#wechat_redirect
叫做故事页面

我们首先进入一个故事页面:直接在首页里点进去,查看它的网址:https://mp.weixin.qq.com/s?__biz=MzA4NzMzMjczMg==&mid=2650878972&idx=1&sn=74c7684b0f5e10b70ce48dfd9dd4e2a4&scene=19#wechat_redirect

我们再在首页里F12看一下控制台,右键页面中《狠毒的王子》条目,点检查
image
框选出来的就是检查到的元素,我们在这附近找一找,就能发现网址 。点进去,确实是到了故事页面。

接下来我们来找一下这个元素的特征。它的class属性是:'list_item js_post',我们先把焦点放到控制台上,点Ctrl+F,搜索一下list_item
image
我们发现,只有在有故事页面的网址的地方,才有list_item

好!我们发现了特征,我们可以通过这个来找网址了。

使用driver.find_elements_by_class_name('list_item')就可以找到一个元素的列表了。这句话的含义是,根据class的name来找元素。至于怎么把元素里的网址提取出来,将是底下“获取元素属性”要说的事情,这里就先不说了。

这里class是list_item js_post,中间有个空格,这个坑可以看一眼第三个参考网址

也有其他方式去定位元素,请详见参考网址。这里不具体说很多。


进入到故事页面,我们还需要找到音频真正的地址。首先,老父亲一开始给我发的那个网址里,帮我避开一个坑:微信公众号需要先点击播放按钮才会有音频的元素出来!! 所以我们需要先点一下播放的按钮,然后去找音频。

如何点击呢?我们只需要找到按钮这个元素btn,btn.click()就可以点击了

定位元素btn也是类似的步骤,这里我是这样做的:driver.find_elements_by_class_name('weui-audio-btn')

最后,我们需要定位到音频元素,我从控制台的element里找了很久都没有找到。后来从百度搜到可以在network里找到类型为media的文件,但依旧不知道怎么用selenium去找这个文件。最终是从老父亲发的那个链接里,把那位博主本来用splinter写的改写成了selenium版的——直接按标签名字找audiodriver.find_element_by_tag_name('audio')

Selenium 获取元素属性

参考网址:https://www.cnblogs.com/yoyoketang/p/6486927.html

element.get_attribute(str)就可以获取对应的属性,括号里参数是一个字符串,写属性名。element是一个元素对象。返回值就是属性的值。

driver.title就是直接获取了当前页面的标题,就是你标签页上显示的。
image

比如在获取故事页面链接:ele.get_attribute('href')
比如在获取最终的音频链接时:au.get_attribute('src')

这里说一下,href就是超链接,src就是引用资源,就比如这篇markdown,参考网址就是类似于href,而嵌入的图片,如下图,代码里也是一个链接,但是显示出来是图片。
image

Part 5 requests下载

其实这部分没怎么研究,就是把老父亲给的链接里的代码改了改。

filepath='D:'+'\\'+title+'.mp3'
open(filepath, 'wb').write(rq.get(h).content)

open涉及到另一个库,os,用来进行文件操作,具体知识可见菜鸟教程:https://www.runoob.com/python/os-file-methods.html
filepath填你想要放置的路径就可以了
rq是在前面调用头文件的时候把requests缩写过来了,用get('链接').content就可以获取那个页面的数据,然后写入本地的文件里。

Part 6 代码解析

再贴一遍代码方便翻页:

from selenium import webdriver
import time
from selenium.webdriver.common.keys import Keys
import requests as rq

if __name__=='__main__':
    driver=webdriver.Firefox()
    base_url='https://mp.weixin.qq.com/mp/homepage?__biz=MzA4NzMzMjczMg==&hid=11&sn=bb7bc45d8a49ff0607153db985d2c2c2&scene=18&uin=&key=&devicetype=Windows+10+x64&version=6302019a&lang=zh_CN&ascene=7&fontgear=2'
    driver.get(base_url)
   # time.sleep(3)

    for i in range(1,10):
        js="var q=document.documentElement.scrollTop=10000"
        driver.execute_script(js)
        time.sleep(1)
    eles=driver.find_elements_by_class_name('list_item')

    num=0
    href=[None]

    for ele in eles:
        href.append(ele.get_attribute('href'))
        num+=1
        
    for i in range(1,num+1):
        driver.get(href[i])
        all_handles = driver.window_handles
        new_handle = all_handles[-1]
        driver.switch_to.window(new_handle)
        time.sleep(3)
        a=driver.find_elements_by_class_name('weui-audio-btn')
        a[-1].click()
        au=driver.find_element_by_tag_name('audio')
        title=driver.title
        h=au.get_attribute('src')
        print(title)
        filepath='D:'+'\\'+title+'.mp3'
        open(filepath, 'wb').write(rq.get(h).content)

driver=webdriver.Firefox()
base_url='https://mp.weixin.qq.com/mp/homepage?__biz=MzA4NzMzMjczMg==&hid=11&sn=bb7bc45d8a49ff0607153db985d2c2c2&scene=18&uin=&key=&devicetype=Windows+10+x64&version=6302019a&lang=zh_CN&ascene=7&fontgear=2'
driver.get(base_url)

先创建webdriver的实例driver,url里填写需要爬的网址,我时间有限没有做UI,就是自己直接改代码里的地址。
接着访问地址。
time.sleep()是为了等页面刷新,网络不好要自己调一调延时的。下文中的time.sleep()都是一样的道理。(括号里填延时的秒数)


for i in range(1,10):
    js="var q=document.documentElement.scrollTop=10000"
    driver.execute_script(js)
    time.sleep(1)
eles=driver.find_elements_by_class_name('list_item')

这里是做几次下拉页面的操作,还是时间有限(toulan)。做细致一点应当是能判断是否到头的,想做的可以自己做,我就直接这样了。
eles是获取了整个首页里的故事页面地址列表,eles是一个由元素组成的队列。


num=0
href=[None]
for ele in eles:
    href.append(ele.get_attribute('href'))
    num+=1

先把地址都存下来。因为你只要切换出去页面,它就找不到那个元素在哪儿了,所以先存地址,免得以后来回换。


for i in range(1,num+1):
    driver.get(href[i])
    all_handles = driver.window_handles
    new_handle = all_handles[-1]
    driver.switch_to.window(new_handle)
    time.sleep(3)
    a=driver.find_elements_by_class_name('weui-audio-btn')
    a[-1].click()
    au=driver.find_element_by_tag_name('audio')
    title=driver.title
    h=au.get_attribute('src')
    print(title)
    filepath='D:'+'\\'+title+'.mp3'
    open(filepath, 'wb').write(rq.get(h).content)

整个循环是打开每一个页面去找地址,然后下载。
a是存储了播放按钮元素,au存储了当前故事页面的音频真实地址。
最后两行把东西下载下来。

Part 7 其他提醒

  • 注意定位元素时element和elements单复数的区别——前者返回一个元素对象,后者返回一个元素对象组成的列表
  • 如果在切换句柄的时候报错,请尝试更新你的getodriver
  • 这个程序莫名其妙有时候下着下着,中间会突然点不到按钮导致程序终止(不点按钮后面就找不到音频元素了),不知道怎么解决。
内容可以为空
posted on 2021-05-13 18:47  heremei  阅读(167)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3