几个月以前在B站发布了几个教程视频,其中使用Python爬取豆瓣TOP250并存入csv文件目前最受欢迎,好多小伙伴也问我要源码,本来准备同步到github的,但是想想直接给源码的方式不利于学习,所以我准备将之后的教程视频发布后再在博客同步发一篇教程视频。
废话不多说,进入正题。
本文用到了Python的requests和lxml库,浏览器插件XPath Helper ,请提前下载安装好。
一、观察网页结构以及拉取数据的方式
我们在爬取一个网页时,首先要对网页元素的布局以及数据的拉取方式进行分析。
我们按下F12(部分电脑需要按下fn+f12),然后刷新页面观察xhr处有没有发起ajax请求。
刷新后,xhr为空,代表网页的数据来自于服务器渲染,我们需要从网页源代码中去提取数据。
二、提取网页数据
提取数据的方式很多,有时候可以混合使用,这里我们使用xpath就可以解决所有的需求。
我们在开发者工具中点击左上角小箭头,然后点击你想爬取的信息,即可自动定位
我们在定位后的dom结构中找到一个全局唯一的父元素,可以是class_name,也可以是id。
比如上图中的图片链接的xpath我就可以写为
//ol/li/div/div[@class='pic']/a/img/@src
同时我们发现img标签的alt属性是包含电影名称的,所以我们也可以通过alt获取电影的名称。
其他的信息获取方法都是类似的,多试几次就行,这里不再赘述。
获取信息的代码如下:
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36"
}
def get_html(start):
url = f'https://movie.douban.com/top250?start={start}&filter='
response = requests.get(url, headers=headers)
print(response.status_code)
html = etree.HTML(response.text) # 将网页字符串转换为element对象
movie_lis = html.xpath("//ol/li")
for li in movie_lis:
title = ''.join(li.xpath("div/div[@class='info']/div[@class='hd']/a/span[1]/text()"))
description = ''.join(li.xpath("div/div[@class='info']/div[@class='bd']/p/text()")).replace('\n', '').replace(' ', '')
rating = ''.join(li.xpath("div/div[@class='info']/div[@class='bd']/div[@class='star']/span[@class='rating_num']/text()"))
comment_num = ''.join(li.xpath("div/div[@class='info']/div[@class='bd']/div[@class='star']/span[4]/text()"))
quote = ''.join(li.xpath("div/div[@class='info']/div[@class='bd']/p[@class='quote']/span/text()"))
cover = ''.join(li.xpath("div/div[@class='pic']/a/img/@src"))
其中,headers是用来防反爬的,具体原理可以在搜索引擎自行搜索了解。
此外,我们点击底部的翻页,发现每页只有start参数在变化,每次增加25,所以采取循环的方式来爬取所有的数据
三、保存数据
我们已经获取到了数据,剩下就是保存了,保存的方式也很多,txt、csv、excel、数据库等等都可以,这里采用pythoner最常用的csv格式。 csv与excel观感上并无不同,只是更利于程序写入,一个半角逗号隔开代表是一列,每一行最后写入一个\n表示本行结束,由这个规则我们可以写出保存数据的函数。如下:
def save_data(title, description, rating, comment_num, quote, cover):
movie_info = f'{title},{description},{rating},{comment_num},{quote},{cover}\n'
fp.write(movie_info)
完整代码
import requests
from lxml import etree
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36"
}
def get_html(start):
print('正在爬取', start)
url = f'https://movie.douban.com/top250?start={start}&filter='
response = requests.get(url, headers=headers)
print(response.status_code)
html = etree.HTML(response.text) # 将网页字符串转换为element对象
movie_lis = html.xpath("//ol/li")
for li in movie_lis:
title = ''.join(li.xpath("div/div[@class='info']/div[@class='hd']/a/span[1]/text()"))
description = ''.join(li.xpath("div/div[@class='info']/div[@class='bd']/p/text()")).replace('\n', '').replace(' ', '')
rating = ''.join(li.xpath("div/div[@class='info']/div[@class='bd']/div[@class='star']/span[@class='rating_num']/text()"))
comment_num = ''.join(li.xpath("div/div[@class='info']/div[@class='bd']/div[@class='star']/span[4]/text()"))
quote = ''.join(li.xpath("div/div[@class='info']/div[@class='bd']/p[@class='quote']/span/text()"))
cover = ''.join(li.xpath("div/div[@class='pic']/a/img/@src"))
save_data(title, description, rating, comment_num, quote, cover)
def save_data(title, description, rating, comment_num, quote, cover):
movie_info = f'{title},{description},{rating},{comment_num},{quote},{cover}\n'
fp.write(movie_info)
if __name__ == '__main__':
fp = open('./豆瓣TOP250.csv', 'a+', encoding='utf-8-sig')
head = '名称,简介,评分,评论人数,引言,封面图\n'
fp.write(head)
for start in range(0, 250, 25):
get_html(start)
fp.close()
代码整体比较简单,如果有疑问可以在评论区提出。
Python 爬虫版权声明:如无特殊说明,文章均为本站原创,转载请注明出处
本文链接:https://www.yangyingqi.com/60.html