学习爬虫Part2-实战:requests+BeautifulSoup实现静态爬取

实战:requests+BeautifulSoup实现静态爬取

静态网页是指一次性加载所有内容的网页,爬虫一次请求便能得到所有信息,对爬虫非常友好。

豆瓣top250电影信息爬取

网站为:https://movie.douban.com/top250

1
打开F12/右键检查第一个电影,分析源码先,发现每个<li>标签就对应着一个电影的信息。

1

1
我们来爬取每部电影的图片,名称,导演演员,类型,评分,和它的一句话总结,继续对<li>标签进行分析,又发现信息又在<div class="info">标签里,而这标签只存在于<li>标签中,其它地方不存在,这样可以用find_all()方法把他们全部分离出来。这里不选择<li>标签是它没有唯一性,电影以外的内容也有<li>标签。

2

1
2
3
4
5
6
7
8
9
10
11
12
13
布置好伪装后就可一开始根据每个<div class="info">标签进行信息筛选了:

图片链接是<div class="info">的上上个兄弟标签<div class="pic">的孙子<img>的src属性的值

电影名有多个,都在<div class="hd">标签里,用get_text()把它们串起来
导演演员是<p class>标签的第一段字符串

类型是<p class>标签的第二段字符串

评分和评分人数都在<div class="star">标签里,又用get_text()串起来
一句话总结直属于<span class="inq">标签

html中的&nbsp对应字符串中的\xa0,可用replace方法替换掉
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
url = 'https://movie.douban.com/top250'
headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36'}
r=requests.get(url,headers=headers)
soup = BeautifulSoup(r.text,'lxml')

for each in soup.find_all('div',class_='info'):
img_url = each.previous_sibling.previous_sibling.a.img['src']#图片链接
'''
with open('*.jpg','wb') as img:#还可以顺便下载回来,名字自起
img.write(requests.get(img_url,headers=headers).content)
'''
title=each.find('div',class_='hd').get_text(strip=True).replace('\xa0','')#标题
actor = list(each.find('p',class_='').strings)[0].strip().replace('\xa0','')#导演演员
type_ = list(each.find('p',class_='').strings)[1].strip().replace('\xa0','')#类型
score = each.find('div',class_='star').get_text('/',strip=True)#评分及人数
quote = each.find('span',class_='inq').string#一句话总结
print([img_url,title,actor,type_,score,quote])#这里只简单打出来看下,怎样存储由你来决定

3

但是这样只有25部电影, ‘https://movie.douban.com/top250' 指向第一页,我们现在只爬了一页,其实还有9页还没爬啊,这是就要构造网址了。

  我们点到第二页,发现网址变成了 https://movie.douban.com/top2?start=25&filter= ,第三页start条件值变成50,我们可以得出结论,每下一页,start条件值就加25。第一页start=0,第二页start=25…..第十页start=225。这样就可以循环构造网页并爬取了.

  另一种思路:网页不是有下一页的按钮吗,右键检查一下,发现它已经包含了要构造的部分了,是一个属性值,提取出来接到原网址上即得到下一页的网址,这样能完全爬取所有页数,不用像上面一样设置循环次数。

4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# -*- coding: utf-8 -*-
import requests
from bs4 import BeautifulSoup


url = 'https://movie.douban.com/top250'
with open('douban.txt','w',encoding='utf-8') as f:
while url :
headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36'}
r=requests.get(url,headers=headers)
soup = BeautifulSoup(r.text,'lxml')
for each in soup.find_all('div',class_='info'):
img_url = each.previous_sibling.previous_sibling.a.img['src']
title=each.find('div',class_='hd').get_text(strip=True).replace('\xa0','')
actor = list(each.find('p',class_='').strings)[0].strip().replace('\xa0','')
#将生成器list化后索引,strip()去除两边空格再用空字符替换&nbsp
type_ = list(each.find('p',class_='').strings)[1].strip().replace('\xa0','')
score = each.find('div',class_='star').get_text('/',strip=True)
if each.find('span',class_='inq'):#注意有部电影没有总结,也就没有<span class="inq">标签这里用if检测一下防止None使用string方法报错
quote = each.find('span', class_='inq').string
else:
quote = '没有总结哦'
f.write(img_url+'\n'+title+'\n'+actor+'\n'+type_+'\n'+score+'\n'+quote+'\n')
f.write('\n')
try:#到最后一页时没有下一页按钮,会报TypeError,这时用try语句让url=None使while循环停止
url = 'https://movie.douban.com/top250' + soup.find('span',class_='next').a['href']
except TypeError:
url = None

5

Donate? comment?