Scrapy 爬取 豆瓣电影的短评
来源:互联网 发布:手机淘宝首页装修布局 编辑:程序博客网 时间:2024/04/30 06:19
之前爬取电影信息的时候,将电影短评的url一并存起来了。
因此爬取电影短评的时候只需将数据库中存在的url 放入start_urls中就好了。
spider.py
# -*- coding: utf-8 -*-from scrapy.selector import Selectorfrom scrapy.spiders import Spiderfrom scrapy.http import Request ,FormRequestfrom comments.items import CommentsItemimport scrapyfrom scrapy import logimport MySQLdbclass CommentSpider(Spider): name = "comments" #allowed_domains=["movie.douban.com"] db = MySQLdb.connect("localhost","root","123456","python" ) cursor = db.cursor() #在爬取电影信息时已经将评论的链接也抓到数据库中(comment_url), 从数据中找到地址 作为 start_urls cursor.execute("select comment_url from doubanmovie") #data = cursor.fetchone() # 取一条 data = cursor.fetchall() #取所有 start_urls = data def parse(self,response): sel = Selector(text=response.body) Url = response.url start_index = Url.find('comments') URL = Url[0:start_index+8] ID = filter(str.isdigit,URL) comments = sel.xpath('//*[@class="comment-info"]') for comment in comments: item = CommentsItem() item['ID'] = ID item['user_name'] = comment.xpath('a/text()').extract() item['user_score'] = comment.xpath('span[1]/@title').extract() yield item for url in sel.xpath("//*[@class='next']/@href").extract(): yield Request(URL+url,callback=self.parse)
运行的时候出错,
显示TypeError(‘Request url must be str or unicode, got %s:’ % type(url).name).
后来发现 是因为 从数据库中取数据,data是 tuple 格式。
直接 start_urls = data; 不合适。因为 在scrapy中 start_urls是List,而且 start_urls中的元素应该是string;
于是添加了一些代码:
temp = list(data) start_urls = [] for i in range(len(temp)): tem = str(temp[i]) tem2 = tem[2:len(tem)-3] start_urls.append(tem2)
这样一来,start_urls 就符合格式了。
然后就是模拟登陆了。
豆瓣爬取短评的时候,不登录只能爬取前几页。这显然是不够的。
scrapy模拟登陆可以使用
from scrapy.http import Request ,FormRequest
而且,scrapy自动处理cookie.
关于模拟登陆,文档上更详细,也有例子:
https://scrapy-chs.readthedocs.org/zh_CN/0.24/topics/request-response.html#scrapy.http.FormRequest.from_response
看 douban 登陆界面的html
<div class="item"> <label>帐号</label> <input id="email" name="form_email" type="text" class="basic-input" maxlength="60" value="邮箱/手机号" tabindex="1"/> </div> <div class="item"> <label>密码</label> <input id="password" name="form_password" type="password" class="basic-input" maxlength="20" tabindex="2"/> </div>
因此
formdata={ 'form_email': '账号', 'form_password': 'passward' },
然后发现,登陆几次后,再登陆就要输验证码。
我的解决方式是,保存验证码的url,在浏览器中打开 手动输入验证码(这样是可以) 然后和账号信息 一起提交
python PIL 可以识别验证码,用之后发现,对于豆瓣的验证码,可以说是 完全识别不出来。
这样一来 登陆之前 先看一下 有没有验证码。
如果有,就手动输入验证码,然后和账号信息一起提交
如果没有 就只发送账号信息
因此在 spider.py中添加代码:
def start_requests(self): yield Request("https://accounts.douban.com/login?source=movie", meta={'cookiejar':1},callback=self.post_login) def post_login(self,response): print 'Preparing login' sel = Selector(response) nodes = sel.xpath("//*[@class='captcha_image']/@src").extract() if nodes : print nodes xerf = raw_input() return scrapy.FormRequest.from_response( response, formdata={ 'captcha-solution': xerf, 'form_email': '账号', 'form_password': 'password' }, callback=self.after_login ) return scrapy.FormRequest.from_response( response, formdata={'form_email': '账号', 'form_password': 'password' }, callback=self.after_login ) def after_login(self,response): #check login succeed before going on if "authentication failed" in response.body: self.log("login failed", level = log.ERROR) for url in self.start_urls : print url yield self.make_requests_from_url(url) #-----------
因为我用的是 spider 不是crawlspider
因此 获取后续url的时候 用了一下代码:
for url in sel.xpath("//[@class='next']/@href").extract(): yield Request(URL+url,callback=self.parse)
这里URL 是request 中的URL
因此需要处理一下。
观察发现 豆瓣评论的url 特点
https://movie.douban.com/subject/1292052/comments?start=24&limit=20&sort=new_score
上面代码 获得的href 是 ‘?’及其后面部分。
因此URL 我们只需要’comments’及其前面的部分。
使用,python 字符串的操作。
Url = response.url start_index = Url.find('comments') #start_index 保存的是 comments 前一个字符的位置 URL = Url[0:start_index+8] #将 comments 加上
综上:
爬短评的代码 就写好了:
# -*- coding: utf-8 -*-from scrapy.selector import Selectorfrom scrapy.spiders import Spiderfrom scrapy.http import Request ,FormRequestfrom comments.items import CommentsItemimport scrapyfrom scrapy import logimport MySQLdbclass CommentSpider(Spider): name = "comments" #allowed_domains=["movie.douban.com"] db = MySQLdb.connect("localhost","root","123456","python" ) cursor = db.cursor() #在爬取电影信息时已经将评论的链接也抓到数据库中(comment_url), 从数据中找到地址 作为 start_urls cursor.execute("select comment_url from doubanmovie") #data = cursor.fetchone() data = cursor.fetchall() temp = list(data) start_urls = [] for i in range(len(temp)): tem = str(temp[i]) tem2 = tem[2:len(tem)-3] start_urls.append(tem2) print start_urls def start_requests(self): yield Request("https://accounts.douban.com/login?source=movie", meta={'cookiejar':1},callback=self.post_login) def post_login(self,response): print 'Preparing login' sel = Selector(response) nodes = sel.xpath("//*[@class='captcha_image']/@src").extract() if nodes : print nodes xerf = raw_input() return scrapy.FormRequest.from_response( response, formdata={ 'captcha-solution': xerf, 'form_email': '1491651205@qq.com', 'form_password': 'wx950417' }, callback=self.after_login ) return scrapy.FormRequest.from_response( response, formdata={'form_email': '1491651205@qq.com', 'form_password': 'wx950417' }, callback=self.after_login ) def after_login(self,response): #check login succeed before going on if "authentication failed" in response.body: self.log("login failed", level = log.ERROR) for url in self.start_urls : print url yield self.make_requests_from_url(url) #----------- def parse(self,response): sel = Selector(text=response.body) Url = response.url start_index = Url.find('comments') URL = Url[0:start_index+8] ID = filter(str.isdigit,URL) comments = sel.xpath('//*[@class="comment-info"]') for comment in comments: item = CommentsItem() item['ID'] = ID item['user_name'] = comment.xpath('a/text()').extract() item['user_score'] = comment.xpath('span[1]/@title').extract() yield item for url in sel.xpath("//*[@class='next']/@href").extract(): yield Request(URL+url,callback=self.parse)
如果用CrawlSpider 的话 可以省略 URL 的操作。
本以为可以将一部电影的所有的短评都爬下来,
但运行之后发现一个问题,走到一定深度,会获取到一个访问会超时的页面,就继续不去了。但换一个页面,爬虫又能继续走,于是一部电影就只能获取一般甚至更少的评论数。
我也不知道是什么原因。似乎是豆瓣的原因,,,。
- Scrapy 爬取 豆瓣电影的短评
- scrapy爬取豆瓣电影
- python-scrapy 实现对豆瓣电影的爬取
- scrapy爬取豆瓣TOP250电影
- scrapy ------ 爬取豆瓣电影TOP250
- scrapy爬取豆瓣top250电影
- 【scrapy】scrapy按分类爬取豆瓣电影基础信息
- 爬取豆瓣TOP250电影的评分、评价人数、短评等信息,并在其保存在sql数据库中。
- 爬取豆瓣的电影
- scrapy爬豆瓣电影
- Python 采用Scrapy爬虫框架爬取豆瓣电影top250
- 爬虫框架scrapy,爬取豆瓣电影top250
- Python爬虫实战:Scrapy豆瓣电影爬取
- 使用scrapy+mongodb爬取豆瓣电影TOP250
- Scrapy教程(一)爬取豆瓣top250电影
- 使用scrapy框架爬取豆瓣电影top250信息
- 用scrapy框架爬取豆瓣Top250电影
- 爬虫实践---Scrapy-豆瓣电影影评&深度爬取
- lua next 用法
- mysql null 值相关规则
- SecureCRT vi彩色显示关键字
- 大数据工程师技能图谱
- canvas-转盘
- Scrapy 爬取 豆瓣电影的短评
- beyond compare 解决文件一样,对比有差异的问题
- qt 中都使用第三方类 :错误:ISO C++ 不允许 声明无类型的‘CClient’
- openstack RPM打包
- 个人对webdriver的理解(三)
- The method makeText(Context, CharSequence, int) in the type Toast is not applicable for the argument
- markdown语法简记
- 手机屏幕向下滑动分页取数据
- 个人对webdriver的理解(四)