前言
借助有效率的工具,可以让我们更加方便的写出爬虫程序。本篇使用request和bs4库爬取豆瓣音乐榜单。
介绍
豆瓣音乐榜单:https://music.douban.com/top250
bs4:Beautiful Soup 4
是一个可以从HTML或XML文件中提取数据的Python库。它能够通过你喜欢的转换器实现惯用的文档导航、查找、修改文档的方式。Beautiful Soup会帮你节省数小时甚至数天的工作时间。
一、获取网页html
def download_page(url):
headers = {
'User-Agent':'查看自己的User-Agent,粘贴到此处'
}
data = requests.get(url, headers=headers).content
return data
不添加headers可能导致403,无法获取网页源码,这是因为操作被服务器认为是爬虫而拒绝访问。服务器通过校验请求的U-A来识别爬虫,这是一种相对简单的反爬虫机制。通过模拟浏览器的U-A,可以解决这个问题。
通常,浏览器在向服务器发送请求的时候,会有一个请求头——User-Agent,它用来标识浏览器的类型。当我们使用requests来发送请求的时候,默认的User-Agent是python-requests/2.8.1。如此我们尝试将User-Agent伪装成浏览器。我们通过手动指定User-Agent为Chrome浏览器(F12–>Network中查看),再次访问得到网页源码。
二、获取当前页歌名
def parse_html(html):
global count
soup = BeautifulSoup(html, "html.parser")
music_list_soup = soup.find('div', attrs={'class': 'indent'})
music_name_list = []
for music_li in music_list_soup.find_all('table'):
detail = music_li.find('div', attrs={'class': 'pl2'})
count += 1
music_name = 'Top ' + str(count)
music_name = music_name + detail.find('a').getText() + '\n'
music_name_list.append(music_name)
next_page = soup.find('span', attrs={'class': 'next'}).find('a')
if next_page:
return music_name_list, next_page['href']
else:
return music_name_list, None
我们使用了beautifulsoup来分析网页源码, 创建bs对象soup,并使用解析器html.parser来解析源码。
按F12–>Element查看网页源码,发现<div class='indent'>
标签下存在歌单(table标签);
用for循环获取所有table,并对每一个table进行分析;
在<div, class='pl2'>
标签下的<a>
标签下发现歌名,
用此detail.find('a').getText()
函数获取a标签下的文字内容,并添加到列表中music_name_list.append(music_name)
,再把列表的元素写进文件就可以了。
注: BeautifulSoup中的find和findAll用法相同,不同之处为find返回的是findAll搜索值的第一个值。
三、翻页
next_page是为了让程序能够翻页,next_page['href']
,获取下一页url,通过while循环来反复访问,进而可以获取完整歌单。
四、代码
最后,完整程序代码如下:
#!/usr/bin/env python
# encoding=utf-8
import requests
from bs4 import BeautifulSoup
import codecs
def download_page(url):
headers = {
'User-Agent':'查看自己的User-Agent,粘贴到此处'
}
data = requests.get(url, headers=headers).content
return data
def parse_html(html):
global count
soup = BeautifulSoup(html, "html.parser")
music_list_soup = soup.find('div', attrs={'class': 'indent'})
music_name_list = []
for music_li in music_list_soup.find_all('table'):
detail = music_li.find('div', attrs={'class': 'pl2'})
count += 1
music_name = 'Top ' + str(count)
music_name = music_name + detail.find('a').getText() + '\n'
music_name_list.append(music_name)
next_page = soup.find('span', attrs={'class': 'next'}).find('a')
if next_page:
return music_name_list, next_page['href']
else:
return music_name_list, None
def main():
url = 'https://music.douban.com/top250'
fp = codecs.open('music', 'w', encoding='utf-8')
while url:
html = download_page(url)
musics, url = parse_html(html)
fp.write(''.join(musics))
print 'done\n'
if __name__ == '__main__':
count = 0
main()