1.爬虫介绍
该豆瓣评论爬虫是伶衣在为大创项目做准备时的副产物,总的来说,是一个功能尚可的基于requests库的爬虫(因为全网都没有找到可以用的所以就自己写了),在这篇博文中,伶衣将介绍这一爬虫的实现原理,并分享源代码。该爬虫的功能为,输入一个电影名称,获取一定页数(可调节)的豆瓣短评。涉及到的爬虫技术有:
- cookie模拟登录
- 利用selenium库,启动chromedriver,从而获取js渲染的网页内容
- 利用xpath提取网页内容
- 利用正则表达式匹配对应字符串
- 写入csv文件
由于python库的不断更新,以及豆瓣网站的动态更新以及变化,爬虫并不总有效,但思路类似,如果看到这篇文章时,出现代码报错,可以邮件联系伶衣,这并不是代码问题,而是更新后导致的代码或是网站变化。
2.前期准备
首先,显然,你需要拥有一个python的IDE,当然,作为一种解释型语言,倒也不是必须。
然后,请使用pip安装以下python库
- requests
- lxml
- selenium
- time
- re
- csv
当拥有了这些环境,你还需要chrome浏览器和对应版本的的chromedriver,这里伶衣就不介绍如何安装了,在各种地方可以找到许多教程,其中有不少很不靠谱的。
3.复制代码
当拥有了以上环境,就可以直接复制代码了(笑),相信大家和伶衣一样,大多数时候找到这样一篇教程,需要的都不是如何去做,为什么这样做,而是想要一个现成的解决方案,所以直接,上代码:
import requests
from lxml import etree
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
import re
import csv
headers ={
'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
'Cookie':'',
#如果你需要爬取多页,你可以放入你自己的cookie,伶衣不便提供(
#这是代码中唯一缺少的片段
}
name =input('请输入电影名称:')
url_douban="https://www.douban.com/search?source=suggest&q="+name
option=webdriver.ChromeOptions()
option.add_argument('--headless')
browser = webdriver.Chrome(options=option)
browser.get(url_douban)
time.sleep(3)
a = browser.find_element(By.XPATH, "//ul/li/div/div/div/div/a")
href = a.get_attribute("href")
print(href)
id = re.match('https.*movie/(.*)',href).group(1)
browser.close()
#print(id)
url = "https://movie.douban.com/subject/"+id+"/comments?status=P"
r = requests.get(url,headers=headers).text
html = etree.HTML(r)
comments = html.xpath('//div[@class="comment"]')
for comment in comments:
grades = comment.xpath('.//span[contains(@class,"rating")]')
texts = comment.xpath('.//span[@class="short"]')
text = texts[0].xpath('./text()')[0]
if len(grades)>0:
grade = grades[0].xpath('./@class')[0][7:8]+'stars'
else:
grade = '暂无评价'
filename = name+'.csv'
with open(filename,'a+',encoding='utf-8-sig') as csvfile:
writer = csv.writer(csvfile)
writer.writerow([text,grade])
for i in range(20,2000,20):
start = str(i)
url = 'https://movie.douban.com/subject/'+id+'/comments?start='+start+"&limit=20&status=P&sort=new_score"
r = requests.get(url,headers=headers).text
html = etree.HTML(r)
comments = html.xpath('//div[@class="comment"]')
for comment in comments:
grades = comment.xpath('.//span[contains(@class,"rating")]')
texts = comment.xpath('.//span[@class="short"]')
text = texts[0].xpath('./text()')[0]
if len(grades)>0:
grade = grades[0].xpath('./@class')[0][7:8]+'stars'
else:
grade = '暂无评价'
filename = name+'.csv'
with open(filename,'a+',encoding='utf-8-sig') as csvfile:
writer = csv.writer(csvfile)
writer.writerow([text,grade])
复制完代码,直接运行就可以了。
4.实现原理
既然看到了这里,说明是想学习靠自己完成一个爬虫了,这很好!
看到这里,也许你会想吐槽,为什么伶衣写的代码没有一点注释,我很想说,是为了让大家方便复制,但不幸的是,这是伶衣的代码习惯比较差,为了快速完成代码,没有写注释,大家不要学习!希望有一天我能改掉这点QwQ
解释原理也就是补充注释的环节了hhh
#导入对应库
import requests
from lxml import etree
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
import re
import csv
#创建请求头
#这里涉及到cookie,因为豆瓣的评论如果不登录只能看前几页,无法爬取,所以使用cookie记录登录状态
#不加cookie也可,能部分爬取
headers ={
'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
'Cookie':'',
#如果你需要爬取多页,你可以放入你自己的cookie,伶衣不便提供(
#这是代码中唯一缺少的片段
}
name =input('请输入电影名称:')
#利用字符串拼接获取所需电影的搜索代码
#建议使用params传参的方式,看起来会专业很多(bushi)
url_douban="https://www.douban.com/search?source=suggest&q="+name
#接下来这部分是用于爬取电影对应id的
#创建webdriver.ChromeOptions实例,用于隐藏浏览器,并作为参数
#这里伶衣使用的是chrome,因为id参数出现在js渲染的内容中,需要打开浏览器,获取elements中的内容
option=webdriver.ChromeOptions()
option.add_argument('--headless')
#开始获取id
browser = webdriver.Chrome(options=option)
browser.get(url_douban)#get方式获取elements
time.sleep(3)#不能省略,如果出现报错,可尝试延长改时间,取决于网速
a = browser.find_element(By.XPATH, "//ul/li/div/div/div/div/a")#利用xpath选择器获取url
#注意,以上是新的语法,很多在当前时间无法使用的函数正是因为selenium库改变了语法
#为了得知这一点,伶衣看了很多攻略,甚至阅读说明文档,怨念极深
#没事改什么语法,giao!
href = a.get_attribute("href")
print(href)
id = re.match('https.*movie/(.*)',href).group(1)#利用正则表达式提取id
browser.close()
#print(id)
#字符串拼接,获取短评的url地址
url = "https://movie.douban.com/subject/"+id+"/comments?status=P"
#使用requests库,并将返回的信息转化为html的格式化信息
r = requests.get(url,headers=headers).text
html = etree.HTML(r)
#利用xpath选择器获取需要的评论
comments = html.xpath('//div[@class="comment"]')
for comment in comments:
#这是一个循环,循环获取单页信息
grades = comment.xpath('.//span[contains(@class,"rating")]')
texts = comment.xpath('.//span[@class="short"]')
text = texts[0].xpath('./text()')[0]
if len(grades)>0:
grade = grades[0].xpath('./@class')[0][7:8]+'stars'
else:
grade = '暂无评价'
#将获取到的内容写入csv,方便后续跑深度学习算法
filename = name+'.csv'
with open(filename,'a+',encoding='utf-8-sig') as csvfile:
writer = csv.writer(csvfile)
writer.writerow([text,grade])
#这个循环用于获取多页信息
#或许会注意到和前面的内容一样,因为每一页和第一页的url不同
for i in range(20,2000,20):
start = str(i)
url = 'https://movie.douban.com/subject/'+id+'/comments?start='+start+"&limit=20&status=P&sort=new_score"
#字符串拼接,这里是观察到,每一页的start参数正好增加“20”
r = requests.get(url,headers=headers).text
html = etree.HTML(r)
comments = html.xpath('//div[@class="comment"]')
for comment in comments:
grades = comment.xpath('.//span[contains(@class,"rating")]')
texts = comment.xpath('.//span[@class="short"]')
text = texts[0].xpath('./text()')[0]
if len(grades)>0:
grade = grades[0].xpath('./@class')[0][7:8]+'stars'
else:
grade = '暂无评价'
filename = name+'.csv'
with open(filename,'a+',encoding='utf-8-sig') as csvfile:
writer = csv.writer(csvfile)
writer.writerow([text,grade])
以上,全部原理解释完毕,因为时间比较紧,所以只写了重点部分,如有疑问可以邮箱联系伶衣,有空会解答。
5.结语
总的来说,伶衣对这个爬虫还挺满意的,但是毕竟伶衣也只是小萌新,如果有什么问题希望可以批评指正!在学习爬虫和写一个实际的爬虫程序的过程中,伶衣获益良多,也接触到一些计算机网络和html对应的知识,如果你也希望学习爬虫,最好对于html、css和js有初步的了解。