动态网页爬虫的解决方案

前言

在复习早期下载视频知识点时,发现有些关键地方没有理清楚。特此梳理

爬虫实践经验小结

要是不精通动态网页爬虫,那爬虫可用武之地就不大了。

关于爬虫的小故事(可略过)

假设有这样一个桌子和椅子,它们有一套默认的规则,人类坐进椅子,桌子便按照规则提供服务
正常情况是,有一个人类,他坐在了椅子上,说,我想要一支笔,于是桌子表面从下面传上来一支笔。但这个人类先要100支笔,桌子做不到。于是人类把桌子抽屉打开,翻了看到了一百只笔所在的位置,并告诉了它的机器人。
静态网页:人类命令它的机器人仆从按照之前告诉它的地址把笔一支支取出来,人类离开椅子,机器人坐进椅子然后完成任务。

动态网页:人类依然是命令机器人按照告诉它的地址把笔取出来,人类离开椅子,机器人坐进椅子。
此时,为了防止机器人仆从自己从抽屉里拿笔,这个桌子不允许非人类看到抽屉的内部除非得到椅子的认可,
人类为了让机器人帮自己拿笔,告诉它自己的屁股形状,让它假装是自己,于是机器人坐在椅子上,能拉开抽屉看到内部了。

但是机器人找不到笔了
**selenium:**原来,机器人是不需要拉抽屉直接把手探进去拿笔的,而人类是需要拉抽屉,笔的位置才能出现的。于是机器人也模仿人类拉抽屉,看到了笔的位置,完成任务
接口:机器人不想通过模仿人类,它看到了抽屉里原本应该放笔的位置上现在有根绳子,顺着这根绳子他发现了一个保险箱。保险箱里有无数个小精怪,而且他们有它所需要的笔。(小精怪们把无数数据拧成一股绳传到抽屉里)保险箱上有很多个转钮,把它们转到指定的位置相应的笔就会出来。机器人注意到每支笔对应的转钮除了一两个其它都是相同的。

动态网页爬虫的解决方案

如今大部分网页都是动态网页,像经典案例豆瓣250排行榜那样的案例那是打着灯笼都找不着了

解决方案就两个

方式 优点 缺点 实践
分析接口 直接可以请求到数据,不需要做一些解析工作。代码量少,性能高 分析接口比较复杂,特别是一些通过js混淆的接口。要有一定的js功底。容易被发现是爬虫 有道接口,b站视频接口,天气app接口
selenium 直接模拟浏览器的行为。浏览器能请求到的,使用selenium也能请求到。爬虫更稳定 代码量多,性能低 scrapy+selenium

通过接口获取数据
第一个例子-----有道词典
第二个例子------b站
第三个例子------百度图片(本文只涉及动态的图片网页)
有道和b站涉及一个重要区别----post请求和get请求的区别

有道的post,浏览器先发送header,然后再发送data,data里面有加密机制,这个机制需要在js文件里面破解,这个js文件是网站向其服务器发送请求时、提交数据包时,通过抓包得来的,是经过美化的需要还原。分析js文件,会找到有关语法指明加密参数的数据来源,可以将这个加密机制复制到代码中,替代js文件的加密

b站的接口----playurl文件在network里找,结果有的视频里有,有的没有

在这里插入图片描述

网上搜到接口是这样的

'https://api.bilibili.com/x/player/playurl?' + 'bvid=' + bvid +'&cid=' + str(cid) + '&qn=64&type=&otype=json'

b站不同类型的视频,在network中获取的数据也是有差异的,
在这里插入图片描述
在这里插入图片描述
抓包技术其实很重要,扩大自己获取数据的能力

有道词典难点它的参数有加密,是post
b站的难点是它不能直接一次获取视频,需要分片下载,似乎没有url的都只能这样下载,由于不是post方式所以不需要参数

第三个例子,见百度图片的获取
首先来到要爬取百度图片的网页,右击检查,点击network,观察有没有包含图片url的接口即数据包
在这里插入图片描述
我没有找到,,,,,这就是我经常遇见的情况-------看别人的例子里都通过这种方法找到了对应的js数据包,我自己却找不到。。。。。。

虽然如此,找接口即找包含需求内容的文件是相当重要的(后来我找到了)

百度图片的接口是

http://image.baidu.com/search/acjson?

加上参数

param = 'tn=resultjson_com&ipn=rj&ct=201326592&is=&fp=result&queryWord={}&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=&hd=1&latest=0&copyright=0&word={}&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&fr=&expermode=&force=&cg=star&pn={}&rn=30&gsm=78&1557125391211='.format(

访问这个接口就能获取图片url了

在这里插入图片描述
放到js解析网站上好看多了
在这里插入图片描述
然后就是下载保存基本操作

另外经常会出现FileNotFoundError: [Errno 2] No such file or directory: ‘D:/base/0.jpg’
可以规范一点操作

cwd = os.getcwd()
        file_name = os.path.join(cwd, keyword)
        if not os.path.exists(keyword):
            os.mkdir(file_name)
        for index, url in enumerate(image_url, start=1):
            with open(file_name + '\\{}.jpg'.format(index), 'wb') as f:
                f.write(content)
            if index != 0 and index % 30 == 0:
                print('{}第{}页下载完成'.format(keyword, index / 30))

在这里插入图片描述
所以以接口下载图片很顺畅

通过selenium获取数据

第一个例子--------腾讯动漫全站漫画
第二个例子--------百度图片(动态版)
第三个例子--------简书点击更多获取文章

腾讯动漫

爬取全站漫画

百度图片

来到网页,观察
滑动鼠标,图片陆续出现但页面没有刷新,所以是动态网页
尝试用xpath普通方法无果后
用selenium
部分代码如下

subjects = driver.find_elements_by_xpath("//div[@class='imgbox']/a/img")
for subject in subjects:

        a = subject.get_attribute("data-imgurl")
        print(a)

简书

来到这个网页,观察网页源代码,右键检查,用xpath helper试一试

发现这个网页有反爬机制,类名是动态的,上代码xpath即使用相对位置搜索也不一定能获取想要的内容,要确定正确的xpath语法会很麻烦

现在要爬取,专题收入对应的链接或文字
在这里插入图片描述

用代码试试
在这里插入图片描述
果然返回为空,无法获取指定的内容

并且原网页需要用户点击更多,所以为了解决这两个特定的问题,使用selenium

看代码

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome(executable_path=r"D:\ProgramApp\chromedriver\chromedriver.exe")

url = "https://www.jianshu.com/p/7e2b63ed0292"
driver.get(url)

WebDriverWait(driver,5).until(
    EC.element_to_be_clickable((By.XPATH,"//section[position()=2]/div/div"))
)

while True:
    try:
        next_btn = driver.find_element_by_xpath("//section[position()=2]/div/div")
        driver.execute_script("arguments[0].click();",next_btn)
    except Exception as e:
        break

subjects = driver.find_elements_by_xpath("//section[position()=2]/div[position()=1]/a")
for subject in subjects:
    print(subject.text)

在这里插入图片描述
结果达到目的
小结:
现状一:用普通方法爬取得到某些东西,爬取不到某些东西
爬取得到的东西在源代码里有,爬取不到的在源代码里没有
推测一:源代码里隐藏的都爬取不到,源码里有的普通方法都能爬取
注:源代码不包括一个很长很长的复杂字符串
现状二:简书网页里,专题名称源代码里没有,但抓包能获取
推测二:源代码里没有的都能抓包获取
意外收获:抓包能获得所有评论,头像,ID等信息
现状三:简书网页,用xpath普通方法爬取不到专题名,用接口可以,用selenium也可以
推测三:源代码隐藏的只能用接口或者selenium方式爬取
实践结论:用selenium即能轻松定位,动态属性是针对普通方法的反爬;
selenium是先获取元素再获取属性值

猜你喜欢

转载自blog.csdn.net/qq_51598376/article/details/113811040