《Selenium大揭秘:如何巧妙爬取动态网页数据》
在数字化浪潮中,数据成为了最宝贵的资源之一。而动态网页,就像是隐藏在数字世界深处的宝藏,吸引着无数开发者和数据分析师的目光。今天,我们就来聊聊如何使用Selenium这个强大的工具,去挖掘这些宝藏。
1.1 动态网页的神秘面纱
想象一下,你正在浏览一个网页,突然看到了一条最新的评论或者一个刚刚更新的帖子。这些内容并不是在你打开网页时就全部加载好的,而是通过服务器端动态发送到你的浏览器上的。这就是动态网页的魅力所在。
1.2 如何辨别动态网页
要想知道一个网页是不是动态的,其实很简单。你只需要右键点击页面,选择“查看网页源代码”,然后搜索你感兴趣的内容。如果找到了,说明这些信息是网页自带的;如果没找到,那就说明这些信息是动态加载的。
2.1 Selenium的强大之处
Selenium,这个名字听起来就像是科幻电影里的主角,实际上它也是一个非常强大的工具。它可以模拟用户在浏览器中的各种操作,比如点击、滚动、输入文字等等。这意味着,我们可以用它来自动化地浏览网页,抓取我们想要的数据。
2.2 Selenium的小缺点
当然,Selenium也不是万能的。由于它需要模拟真实的用户操作,所以它的速度会比直接请求网页慢一些。而且,有时候它还会被验证码拦下来,就像你在网上购物时需要输入验证码一样。
接下来,让我们通过一个实际的例子来看看如何使用Selenium来爬取B站的评论。假设我们想要获取某个视频下的所有评论,我们可以这样做:
- 启动浏览器驱动:这就像是我们要去探险,首先得准备好装备。我们用Selenium启动Edge浏览器,并打开目标网页。
- 查找并点击评价链接:这就像是我们在网页中寻找宝藏的入口。我们用find_element方法找到评价链接,并点击它。
- 等待并点击“有用”按钮:有时候,网页上的内容不是一下子就能加载完的,我们需要耐心等待。我们用WebDriverWait等待“有用”按钮出现,并点击它。
- 爬取评论:这就像是我们在宝藏即将被别人抢光一样,要赶快行动。我们用一个循环来不断查找评论元素,并把它们添加到一个列表中。
- 处理分页:如果评论很多,网页会分页显示。我们点击“下一页”按钮,继续爬取下一页的评论。
让我们来深入了解一下这段代码。比如这个find_element方法,它就像是一个寻宝地图,可以帮助我们在网页中找到特定的元素。而WebDriverWait则像是一个耐心的守候者,它可以等待某个条件成立,比如某个元素出现或者某个时间过去。
随着互联网的不断发展,动态网页的数量和复杂性也在不断增加。Selenium作为一种强大的工具,能够帮助我们更好地应对这些挑战。未来,随着技术的进步,Selenium的功能和应用场景也将不断扩大。
通过本文的介绍,相信你对如何使用Selenium爬取动态网页有了更深入的了解。无论是数据分析还是信息抓取,掌握这些技能都将大大提升你的工作效率。希望你能在这个充满挑战和机遇的领域中,找到属于自己的宝藏。
用Python爬取六大平台的弹幕、评论,看这一篇就够了
今天讲解如何用python爬取芒果TV、腾讯视频、B站、爱奇艺、知乎、微博这几个常见常用的影视、舆论平台的弹幕和评论,这类爬虫得到的结果一般用于娱乐、舆情分析,如:新出一部火爆的电影,爬取弹幕评论分析他为什么这么火;微博又出大瓜,爬取底下评论看看网友怎么说,等等这娱乐性分析。
本文爬取一共六个平台,十个爬虫案例,如果只对个别案例感兴趣的可以根据:芒果TV、腾讯视频、B站、爱奇艺、知乎、微博这一顺序进行拉取观看。完整的实战源码已在文中,我们废话不多说,下面开始操作!
本文以爬取电影《悬崖之上》为例,讲解如何爬取芒果TV视频的弹幕和评论!
网页地址:
弹幕数据所在的文件是动态加载的,需要进入浏览器的开发者工具进行抓包,得到弹幕数据所在的真实url。当视频播放一分钟它就会更新一个json数据包,里面包含我们需要的弹幕数据。
得到的真实url:
可以发现,每条url的差别在于后面的数字,首条url为0,后面的逐步递增。视频一共120:20分钟,向上取整,也就是121条数据包。
结果展示:
芒果TV视频的评论需要拉取到网页下面进行查看。评论数据所在的文件依然是动态加载的,进入开发者工具,按下列步骤进行抓包:Network→js,最后点击查看更多评论。
加载出来的依然是js文件,里面包含评论数据。得到的真实url:
其中有差别的参数有page和_,page是页数,_是时间戳;url中的时间戳删除后不影响数据完整性,但里面的callback参数会干扰数据解析,所以进行删除。最后得到url:
数据包中每页包含15条评论数据,评论总数是2527,得到最大页为169。
结果展示:
本文以爬取电影《革命者》为例,讲解如何爬取腾讯视频的弹幕和评论!
网页地址:
依然进入浏览器的开发者工具进行抓包,当视频播放30秒它就会更新一个json数据包,里面包含我们需要的弹幕数据。
得到真实url:
其中有差别的参数有timestamp和_。_是时间戳。timestamp是页数,首条url为15,后面以公差为30递增,公差是以数据包更新时长为基准,而最大页数为视频时长7245秒。依然删除不必要参数,得到url:
结果展示:
腾讯视频评论数据在网页底部,依然是动态加载的,需要按下列步骤进入开发者工具进行抓包:
点击查看更多评论后,得到的数据包含有我们需要的评论数据,得到的真实url:
https://video.coral.qq.com/varticle/6655100451/comment/v2?callback=_varticle6655100451commentv2&orinum=10&oriorder=o&pageflag=1&cursor=0&scorecursor=0&orirepnum=2&reporder=o&reppageflag=1&source=132&_=1628948867522https://video.coral.qq.com/varticle/6655100451/comment/v2?callback=_varticle6655100451commentv2&orinum=10&oriorder=o&pageflag=1&cursor=6786869637356389636&scorecursor=0&orirepnum=2&reporder=o&reppageflag=1&source=132&_=1628948867523
url中的参数callback以及_删除即可。重要的是参数cursor,第一条url参数cursor是等于0的,第二条url才出现,所以要查找cursor参数是怎么出现的。经过我的观察,cursor参数其实是上一条url的last参数:
效果展示:
本文以爬取视频《“ 这是我见过最拽的一届中国队奥运冠军”》为例,讲解如何爬取B站视频的弹幕和评论!
网页地址:
B站视频的弹幕不像腾讯视频那样,播放视频就会触发弹幕数据包,他需要点击网页右侧的弹幕列表行的展开,然后点击查看历史弹幕获得视频弹幕开始日到截至日链接:
链接末尾以oid以及开始日期来构成弹幕日期url:
https://api.bilibili.com/x/v2/dm/history/index?type=1&oid=384801460&month=2021-08
在上面的的基础之上,点击任一有效日期即可获得这一日期的弹幕数据包,里面的内容目前是看不懂的,之所以确定它为弹幕数据包,是因为点击了日期他才加载出来,且链接与前面的链接具有相关性:
得到的url:
url中的oid为视频弹幕链接的id值;data参数为刚才的的日期,而获得该视频全部弹幕内容,只需要更改data参数即可。而data参数可以从上面的弹幕日期url获得,也可以自行构造;网页数据格式为json格式
结果展示:
B站视频的评论内容在网页下方,进入浏览器的开发者工具后,只需要向下拉取即可加载出数据包:
得到真实url:
两条urlnext参数,以及_和callback参数。_和callback一个是时间戳,一个是干扰参数,删除即可。next参数第一条为0,第二条为2,第三条为3,所以第一条next参数固定为0,第二条开始递增;网页数据格式为json格式。
结果展示,获取的内容不包括二级评论,如果需要,可自行爬取,操作步骤差不多:
本文以爬取电影《哥斯拉大战金刚》为例,讲解如何爬爱奇艺视频的弹幕和评论!
网页地址:
爱奇艺视频的弹幕依然是要进入开发者工具进行抓包,得到一个br压缩文件,点击可以直接下载,里面的内容是二进制数据,视频每播放一分钟,就加载一条数据包:
得到url,两条url差别在于递增的数字,60为视频每60秒更新一次数据包:
br文件可以用brotli库进行解压,但实际操作起来很难,特别是编码等问题,难以解决;在直接使用utf-8进行解码时,会报以下错误:
在解码中加入ignore,中文不会乱码,但html格式出现乱码,数据提取依然很难:
小刀被编码弄到头疼,如果有兴趣的小伙伴可以对上面的内容继续研究,本文就不在进行深入。所以本文采用另一个方法,对得到url进行修改成以下链接而获得.z压缩文件:
之所以如此更改,是因为这是爱奇艺以前的弹幕接口链接,他还未删除或修改,目前还可以使用。该接口链接中1078946400是视频id;300是以前爱奇艺的弹幕每5分钟会加载出新的弹幕数据包,5分钟就是300秒,《哥斯拉大战金刚》时长112.59分钟,除以5向上取整就是23;1是页数;64为id值的第7为和第8为数。
结果展示:
爱奇艺视频的评论在网页下方,依然是动态加载的内容,需要进入浏览器的开发者工具进行抓包,当网页下拉取时,会加载一条数据包,里面包含评论数据:
得到的真实url:
第一条url加载的是精彩评论的内容,第二条url开始加载的是全部评论的内容。经过删减不必要参数得到以下url:
区别在于参数last_id和page_size。page_size在第一条url中的值为10,从第二条url开始固定为20。last_id在首条url中值为空,从第二条开始会不断发生变化,经过我的研究,last_id的值就是从前一条url中的最后一条评论内容的用户id(应该是用户id);网页数据格式为json格式。
结果展示:
本文以爬取知乎热点话题《如何看待网传腾讯实习生向腾讯高层提出建议颁布拒绝陪酒相关条令?》为例,讲解如爬取知乎回答!
网页地址:
经过查看网页源代码等方式,确定该网页回答内容为动态加载的,需要进入浏览器的开发者工具进行抓包。进入Noetwork→XHR,用鼠标在网页向下拉取,得到我们需要的数据包:
得到的真实url:
url有很多不必要的参数,大家可以在浏览器中自行删减。两条url的区别在于后面的offset参数,首条url的offset参数为0,第二条为5,offset是以公差为5递增;网页数据格式为json格式。
结果展示:
本文以爬取微博热搜《霍尊手写道歉信》为例,讲解如何爬取微博评论!
网页地址:
微博评论是动态加载的,进入浏览器的开发者工具后,在网页上向下拉取会得到我们需要的数据包:
得到真实url:
https://m.weibo.cn/comments/hotflow?id=4669040301182509&mid=4669040301182509&max_id_type=0https://m.weibo.cn/comments/hotflow?id=4669040301182509&mid=4669040301182509&max_id=3698934781006193&max_id_type=0
两条url区别很明显,首条url是没有参数max_id的,第二条开始max_id才出现,而max_id其实是前一条数据包中的max_id:
但有个需要注意的是参数max_id_type,它其实也是会变化的,所以我们需要从数据包中获取max_id_type:
实战代码import reimport requestsimport pandas as pdimport timeimport randomdf = pd.DataFrame()try:a = 1while True:header = {\’User-Agent\’: \’Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 UBrowser/4.0.3214.0 Safari/537.36\’}resposen = requests.get(\’https://m.weibo.cn/detail/4669040301182509\’, headers=header)# 微博爬取大概几十页会封账号的,而通过不断的更新cookies,会让爬虫更持久点…cookie = [cookie.value for cookie in resposen.cookies] # 用列表推导式生成cookies部件headers = {# 登录后的cookie, SUB用登录后的\’cookie\’: f\’WEIBOCN_FROM={cookie[3]}; SUB=; _T_WM={cookie[4]}; MLOGIN={cookie[1]}; M_WEIBOCN_PARAMS={cookie[2]}; XSRF-TOKEN={cookie[0]}\’,\’referer\’: \’https://m.weibo.cn/detail/4669040301182509\’,\’User-Agent\’: \’Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 UBrowser/4.0.3214.0 Safari/537.36\’}if a == 1:url = \’https://m.weibo.cn/comments/hotflow?id=4669040301182509&mid=4669040301182509&max_id_type=0\’else:url = f\’https://m.weibo.cn/comments/hotflow?id=4669040301182509&mid=4669040301182509&max_id={max_id}&max_id_type={max_id_type}\’html = requests.get(url=url, headers=headers).json()data = html[\’data\’]max_id = data[\’max_id\’] # 获取max_id和max_id_type返回给下一条urlmax_id_type = data[\’max_id_type\’]for i in data[\’data\’]:screen_name = i[\’user\’][\’screen_name\’]i_d = i[\’user\’][\’id\’]like_count = i[\’like_count\’] # 点赞数created_at = i[\’created_at\’] # 时间text = re.sub(r\'<[^>]*>\’, \’\’, i[\’text\’]) # 评论print(text)data_json = pd.DataFrame({\’screen_name\’: [screen_name], \’i_d\’: [i_d], \’like_count\’: [like_count], \’created_at\’: [created_at],\’text\’: [text]})df = pd.concat([df, data_json])time.sleep(random.uniform(2, 7))a += 1except Exception as e:print(e)df.to_csv(\’微博.csv\’, encoding=\’utf-8\’, mode=\’a+\’, index=False)print(df.shape)
结果展示:
以上便是今天的全部内容了,如果你喜欢今天的内容,希望你能在下方点个赞和在看支持我,谢谢!
本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com
文章为作者独立观点不代本网立场,未经允许不得转载。