requests+BeautifulSoup爬取猫眼电影

目标

提取的站点URL为http://maoyan.com/board/4,提取的结果会以文件形式保存下来。

函数

分为几个部分,分别是:

  • 获取单个网页的内容,解析单个网页;
  • 解析整个网页多个项目,并且每个项目返回dict(使用field);
  • 存储数据;
  • 生成需要爬取的多个网页,并且调用上述函数进行爬取和存储。

获取单个网页内容

1
2
3
4
5
6
7
8
9
10
def get_one_page(url, headers):
try:

response = requests.get(url=url, headers=headers)
if response.status_code == 200:
return response.text
return None
except RequestException as e:
print(e)
return None

传入url和headers,使用异常类进行捕获。

解析

1
2
3
4
5
6
7
8
9
10
11
def parse_one_page(html):
bs_obj = BeautifulSoup(html)
items = bs_obj.find_all("dd")
for item in items:
yield {
'img': item.find('img', {'class': 'board-img'}).get('data-src'),
'title': item.find('p', {'class': 'name'}).find('a').get('title').strip(),
'stars': item.find('p', {'class': 'star'}).text.strip(),
'time': item.find('p', {'class': 'releasetime'}).text.strip(),
'score': item.find('i', {'class': 'integer'}).text + item.find('i', {'class': 'fraction'}).text
}

分析网页可以知道dd标签分割每个项目,将单个项目拿出来,使用BeautifulSoup进行解析,使用yield返回数据。

文件写入

1
2
3
def write_to_file(content):
with open('result.txt', 'a', encoding='utf8') as f:
f.write(json.dumps(content, ensure_ascii=False) + '\n')

使用with,可以保证异常关闭;使用a,可以保证写入不清空;使用utf8和json存储时的ensure_ascii=False,可以使写入数据为utf8编码。

翻页爬取

1
2
3
4
5
6
7
8
9
10
11
def main(offset):
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/71.0.3578.98 Safari/537.36'
}
url = 'https://maoyan.com/board/4?offset=' + str(offset)

html = get_one_page(url, headers)
for item in parse_one_page(html):
print(item)
write_to_file(item)

跳转页面,可以发现网址从http://maoyan.com/board/4变为了http://maoyan.com/board/4?offset=10。

比之前的URL多了一个参数,那就是offset=10,而目前显示的结果是排行11~20名的电影,初步推断这是一个偏移量的参数。再点击下一页,发现页面的URL变成了http://maoyan.com/board/4?offset=20,参数offset变成了20,而显示的结果是排行21~30的电影。

由此可以总结出规律,offset代表偏移量值,如果偏移量为n,则显示的电影序号就是n+1到n+10,每页显示10个。所以,如果想获取TOP100电影,只需要分开请求10次,而10次的offset参数分别设置为0、10、20、…90即可,这样获取不同的页面之后,再用正则表达式提取出相关信息,就可以得到TOP100的所有电影信息了。

main方法

最后,实现main()方法来调用前面实现的方法,将单页的电影结果写入到文件。相关代码如下:

1
2
3
if __name__ == '__main__':
for i in range(10):
main(i*10)

如果需要考虑爬虫过快,可以在后面加一个sleep:

1
2
3
4
if __name__ == '__main__':
for i in range(10):
main(i*10)
time.sleep(1)

使用多进程

将main的代码改成:

1
2
3
4
5
if __name__ == '__main__':

# 使用多进程
pool = Pool()
pool.map(main, [i * 10 for i in range(10)])

引入

1
from multiprocessing import Pool

如果使用多进程,想要防止爬虫过快,可以在main函数里加一个sleep

1
2
3
4
5
6
7
8
9
10
11
12
def main(offset):
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/71.0.3578.98 Safari/537.36'
}
url = 'https://maoyan.com/board/4?offset=' + str(offset)

html = get_one_page(url, headers)
for item in parse_one_page(html):
print(item)
write_to_file(item)
time.sleep(1)

-------------本文结束 感谢您的阅读-------------