js 爬虫抓取网页数据(web自动化终极爬虫:百度音乐(静态网页)分析步骤)

优采云 发布时间: 2022-01-19 17:12

  js 爬虫抓取网页数据(web自动化终极爬虫:百度音乐(静态网页)分析步骤)

  介绍:

  最近写了几个简单的爬虫,踩了几个深坑。在这里总结一下,给大家写爬虫时的一些思路。该爬虫的内容包括:静态页面的爬取。动态页面的抓取。网络自动化的终极爬虫。

  分析:

  数据获取(主要通过爬虫)

  数据存储(python excel存储)

  数据采集​​实践:百度音乐(静态网页)

  分析步骤

  1.打开百度音乐:

  2.打开浏览器调试模式F12,选择Network+all模式

  

  3.在搜索框搜索歌曲(beat it),查看控制台

  

  4、通过以上分析:获取有效信息:

  5、通过有效信息设计爬虫,获取数据

  代码

  1.View提供了访问参数url并返回结果的方法

  def view(url):

'''

:param url: 待爬取的url链接

:return:

'''

# 从url中获取host

protocol, s1 = urllib.splittype(url)

host, s2 = urllib.splithost(s1)

# 伪装浏览器,避免被kill

headers = {

'Host': host,

'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.78 Safari/537.36',

'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',

'Accept-Encoding': 'gzip, deflate',

'Accept-Language': 'zh-CN,zh;q=0.8',

}

# 代理

proxies = {

"http": "dev-proxy.oa.com:8080",

"https": "dev-proxy.oa.com:8080",

}

# 利用requests封装的get方法请求url,并添加请求头和代理,获取并返回请求结果。并进行异常处理

try:

res = requests.get(url, headers=headers, proxies=proxies)

res.encoding = 'utf-8'

if res.status_code == 200:

# 请求成功

# 获取网页内容,并返回

content = res.text

return content

else:

return None

except requests.RequestException as e:

# 异常处理

print(e)

return None

  2 .search_baidu_song 提供参数song_name的歌曲搜索并获取搜索结果

  def search_baidu_song(song_name):

'''

获取百度音乐搜索歌曲结果

:param song_name: 待搜索歌曲名

:return: 搜索结果

'''

def analyse():

'''

静态网页分析,利用BeautifulSoup,轻松获取想要的数据。需要对html有了解。

:return:

'''

# 初始化BeautifulSoup对象,并指定解析器为 lxml。还有其他的解析器:html.parser、html5lib等

# 详细教程可访问:http://cuiqingcai.com/1319.html《Python爬虫利器二之Beautiful Soup的用法》

html = BeautifulSoup(content, "lxml")

# beautifulsoupzui常用方法之一: find_all( name , attrs , recursive , text , **kwargs )

# find_all() 方法搜索当前tag的所有tag子节点, 并判断是否符合过滤器的条件

# tag标签名为'div'的并且标签类名为class_参数(可为 str、 list、 tuple),

search_result_divs = html.find_all('div', class_=['song-item clearfix ', 'song-item clearfix yyr-song'])

for div in search_result_divs:

# find() 方法搜索当前tag的所有tag子节点, 并返回符合过滤器的条件的第一个结点对象

song_name_str = div.find('span', class_='song-title')

singer = div.find('span', class_='singer')

album = div.find('span', class_='album-title')

# 此部分需要对html页面进行分析,一层层剥开有用数据并提取出来

if song_name_str:

# 获取结点对象内容,并清洗

song_name_str = song_name.text.strip()

else:

song_name_str = ''

if singer:

singer = singer.text.strip()

else:

singer = ''

if album:

album = album.find('a')

if album:

# 获取标签属性值

# 方法二:属性值 = album['属性名']

album = album.attrs.get('title')

if album and album != '':

album = album.strip()

else:

album = ''

else:

album = ''

# print song_name + " | " + singer + " | " + album

songInfoList.append(SongInfo(song_name_str, singer, album))

songInfoList = []

url = urls.get('baidu_song')

url1 = url.format(song_name=song_name, start_idx=0)

content = self.view(url1)

if not content:

return []

analyse(content)

url2 = url.format(song_name=song_name, start_idx=20)

content = self.view(url2)

analyse(content)

return songInfoList[0:30]

  这样我们就得到了百度网歌搜索结果的数据。然后就是保存数据了,这个我们最后会讲。

  网易云音乐(动态网页)

  当我们通过上述静态网页获取方式获取网易云音乐的数据时,可能会遇到这样一个问题:网页的源代码没有可用的数据,只有网页的骨架。数据根本找不到,但是打开开发者工具查看DOM树,就可以找到想要的数据了。这时候我们遇到一个动态网页,数据是动态加载的。无法获取网页数据。

  目前有两种解决方案:

  通过查看访问动态数据界面获取数据。获取网页源代码,通过网络自动化工具获取数据。

  (目前网易云已经不能单纯通过访问url获取数据了,我们可以使用web自动化工具selenium和PhantomJS获取网页源代码) 方案一实现(通过查看动态数据接口获取数据):开启网易云音乐:打开浏览器调试模式F12,选择网络+全部模式

  

  在搜索框中搜索歌曲(击败它),检查控制台

  

  过滤到XHR的请求,发现请求名是一样的。这时候,我们看这些名字,看到Request URL中查找关键字搜索的请求。这个请求是一个 POST 请求。这应该是获取搜索数据的接口,通过查看响应或者预览来查看请求返回结果。正是我们想要的。

  

  我们先不要太高兴,我们还没有弄清楚表单数据是如何组成的。params + encSecKey 究竟是如何生成的。我看过网上关于爬网易评论“如何爬网易云音乐?”的评论数。》,得知网易对api进行了加密。因为个人道教太浅了,看不懂这里加密参数的顺序和内容。所以这个方案放弃了。实在不甘心,只好改方案二。

  选项 2 实现:

  既然第一个方案暂时行不通,也不能影响我们的工作进度,我们继续换一种思路走。我认为使用 web 自动化测试工具 selenium 可以模拟手动操作浏览器。用这种方式导出网页数据应该没问题,我想马上就做。

  安装selenium的环境配置

  建议自动使用python包管理工具:pip install -y selenium

  其他方法请参考:selenium + python自动化测试环境搭建

  2.安装PhantomJS

  PhantomJS 是一个基于 webkit 的 JavaScript API。它使用 QtWebKit 作为其核心浏览器功能,并使用 webkit 来编译、解释和执行 JavaScript 代码。您可以在基于 webkit 的浏览器中做的任何事情,它都能做到。它不仅是一个不可见的浏览器,提供诸如 CSS 选择器、对 Web 标准的支持、DOM 操作、JSON、HTML5、Canvas、SVG 等,它还提供处理文件 I/O 的操作,让您可以读写文件到操作系统等。PhantomJS的用途很广泛,比如网络监控、网页截图、免浏览器网页测试、页面访问自动化等等。

  下载 PhantomJS

  目前官方支持三种操作系统,包括windows\Mac OS\Linux这三大主流的环境。你可以根据你的运行环境选择要下载的包

  1.安装 PhantomJS

  下载后解压文件,将phantomjs.exe放到pythond目录下(C:\Python27\phantomjs.exe)。这样后续加载就不需要指定目录了。也可以放在特定的目录下,使用时可以指定phantomjs.exe的路径。双击打开phantomjs.exe,验证安装成功。如果出现下图,则安装成功。

  

  2.实现的代码步骤:

  def dynamic_view(url):

'''

使用自动化工具获取网页数据

:param url: 待获取网页url

:return: 页面数据

'''

# 初始化浏览器driver

driver = webdriver.PhantomJS()

# 浏览器driver访问url

driver.get(url)

# 坑:不同frame间的转换(网易云在数据展示中会将数据动态添加到'g_iframe'这个框架中,如果不切换,会报"元素不存在"错误。)

driver.switch_to.frame("g_iframe")

# 隐式等待5秒,可以自己调节

driver.implicitly_wait(5)

# 设置10秒页面超时返回,类似于requests.get()的timeout选项,driver.get()没有timeout选项

driver.set_page_load_timeout(10)

# 获取网页资源(获取到的是网页所有数据)

html = driver.page_source

# 坑:退出浏览器driver,必须手动退出driver。

driver.quit()

# 返回网页资源

return html

  

  def search_163_song(song_name):

pass

  也用于通过 BeautifulSoup 对网页资源进行对象化,通过过滤对象获取数据。没想到网易云音乐的数据也可以通过这种方式获取。对于大多数 网站 来说,能够做到这一点就足够了。

  选择 PhantomJS 是因为它不需要可视页面,而且它节省了内存使用。但也有问题,请继续往下看。看起来快完成了。

  3. 发现

  解决方案:使用 Web 自动化获取数据。通过请求动态数据接口获取数据方案实现:

  计划一:

  使用网页自动化工具获取数据:配置同网易云配置,模仿用户操作浏览器打开网页,用户登录,进入搜索页面,获取页面数据

  def spotify_view(url):

'''

使用自动化工具获取网页数据

:param url: 待获取网页url

:return: 页面数据

'''

spotify_name = 'manaxiaomeimei'

spotify_pass = 'dajiagongyong'

spotify_login = 'https://accounts.spotify.com/en/login'

# 初始化浏览器driver

driver = webdriver.PhantomJS()

# 模拟用户登录()

# 浏览器driver访问登录url

driver.get(spotify_login)

# 休息一下等待网页加载。(还有另一种方式:driver.implicitly_wait(3))

time.sleep(3)

# 获取页面元素对象方法(本次使用如下):

# find_element_by_id : 通过标签id获取元素对象 可在页面中获取到唯一一个元素,因为在html规范中。一个DOM树中标签id不能重复

# find_element_by_class_name : 通过标签类名获取元素对象,可能会重复(有坑)

# find_element_by_xpath : 通过标签xpath获取元素对象,类同id,可获取唯一一个元素。

# 获取页面元素对象--用户名

username = driver.find_element_by_id('login-username')

# username.clear()

# 坑:获取页面元素对象--密码

# 在通过类名获取标签元素中,遇到了无法定位复合样式,这时候可采用仅选取最后一个使用的样式作为参数,即可(稳定性不好不建议使用。尽量使用by_id)

# password = driver.find_element_by_class_name('form-control input-with-feedback ng-dirty ng-valid-parse ng-touched ng-empty ng-invalid ng-invalid-required')

password = driver.find_element_by_class_name('ng-invalid-required')

# password.clear()

# 获取页面元素对象--登录按钮

login_button = driver.find_element_by_xpath('/html/body/div[2]/div/form/div[3]/div[2]/button')

# 通过WebDriver API调用模拟键盘的输入用户名

username.send_keys(spotify_name)

# 通过WebDriver API调用模拟键盘的输入密码

password.send_keys(spotify_pass)

# 通过WebDriver API调用模拟鼠标的点击操作,进行登录

login_button.click()

# 休息一下等待网页加载

driver.implicitly_wait(3)

# 搜索打开歌曲url

driver.get(url)

time.sleep(5)

# 搜索获取网页代码

html = driver.page_source

return html

  

  打完跑步后,一切都很好。突然代码报错(如下图)。查了资料后,代码也做了修改。

  

  网络产品

  将 clear() 添加到输入元素以清除原创字符。更换浏览器

  方案实施:

  计划一:

  获取到对象后,为对象添加clear方法(username.clear()、password.clear())

  实施成果

  方案 1 失败。原因不清楚,大部分webdriver不兼容PhantomJS。

  场景二:

  换个浏览器,这次选择使用chrome浏览器来自动化操作。

  安装 chrome 自动化控制插件。

  我认为这将是获取数据的方式。烧鹅,还是没拿到,报错(如下图)

  

  此时:是时候查看请求并找出令牌是什么了。并尝试将令牌添加到请求标头。

  

  查看 cookie

  

  但是我们登录后cookies列表中并没有这样的cookie!

  

  据预测,该 cookie 应在网络播放器加载时播种。验证它:

  

  从上表可以看出。加载播放器时会播种此令牌。

  至此,问题解决了一大半。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线