前一段时间爬取了天猫某些商品的评论数据并进行轻度处理,今天就跟大家聊聊见解吧!
话不多说直接开始:
大家都知道淘宝天猫作为国内最大的电商平台之一, 它对网站的加工是极好的,网站的配置也是非常完美的,其中就包括了反爬虫的设计. 淘宝的登录页面是可以检测selenium操作的,所以用selenium模拟登录是不可行的,只要你用selenium模拟登录不管怎么样都是失败的.但是我们可以带cookie直接登录的,当然这个很简单用requests带cookie访问就OK了,那么我们应该怎么用Scrapy + selenium模拟浏览器拿到数据呢?很简单
首先我们来说怎么登录到淘宝,其实我们Scrapy直接请求需要爬取的店铺的网址,当然不要先模拟登录,因为铁定被查到,然后禁止.当我们直接请求的时候回得到这样的页面: 直接转到商品页面,会弹出一个二维码,这个时候你可以扫码登录,或者点掉,并不影响整个爬取.
当然今天我又看了一下,cookie都不用带直接就可以进去拿数据了,当然我说的是selenium模拟浏览器的方法.
还有就是聊聊下一个点, 我们进入页面看到的是这样的页面
初始页面是拿不到评价数据的, 我们只能拿到商品信息, 商品详情, 以及销售量等的信息, 这也就是我们为什么要用selenium的原因, 我们可以用selenium模拟浏览器点击页面, 跳转到评价页面,然后模拟滚动条滚动, 并模拟点击下一页以便拿到所有的数据
现在来展示一下代码:
这只是selenium模拟浏览器在Scrapy中的用法,现在咱们来解析一下代码:
class SeleniumMiddlewares(object): def __init__(self): self.options = Options() # self.options.add_argument('-headless') 初始化Chrome驱动以便驱动谷歌浏览器,当然你也可以用firbox火狐浏览器, 这个根据你的驱动下载位置填写 self.browser = webdriver.Chrome(executable_path=r"E:\爬虫\ziliao\chromedriver", chrome_options=self.options) def process_request(self, request, spider): page参数是根据spider中请求带来的参数,当参数为一的时候点击累积评价进去评价页面 if int(request.meta["page"]) == 1: self.browser.get(request.url) time.sleep(5) for y in range(10): 模拟滚动条滚动,一次滚动220px, 一个滚动10次 self.browser.execute_script("window.scrollBy(0,220)") time.sleep(0.2) 找到累积评价的标签并点击 pages = self.browser.find_element_by_xpath('//li/a[@href="#J_Reviews"]') pages.click() time.sleep(5) 返回页面相应给spider return HtmlResponse(url=self.browser.current_url,body=self.browser.page_source,request=request,encoding="utf-8") 当带来的参数为2时,进行翻页点击操作 if int(request.meta["page"]) == 2: for y in range(20): 模拟滚动20次,每次200px self.browser.execute_script("window.scrollBy(0,200)") time.sleep(0.2) 找到下一页标签, 并点击 pages = self.browser.find_element_by_link_text("下一页>>") self.browser.execute_script("arguments[0].click();", pages) # pages.click() return HtmlResponse(url=self.browser.current_url, body=self.browser.page_source, request=request,encoding="utf-8")
其实整个爬虫项目的难点就在于这个模拟点击下一页了,当然也可以不用selenium,那么你就去分析接口吧, 也不难,不过不适用通用爬虫, 因为每个网页的接口都是不一样的.言归正传,下面来看看spider的代码吧!因为很简单我就带着大家过一遍就行了.
其实我们做的这个只是最简单的爬取一个页面的需求,毕竟是给大家分享的,所以也不需要太难,原理都是一样,大家会了以后自己做就行了.
而我们这个简单的爬取因为没有网页嵌套所以我们就只需要拿到selenium传回来的数据进行解析就好了, 我们也就用xpath拿到了买家评论, 店家回复, 买家会员等级以及最佳评论这四个, 当然你也可以拿到商品的各种数据, 原理是一样的,这里我就不再一一操作了.话不多说看代码:
class EveSpider(scrapy.Spider): name = 'eve' # allowed_domains = ['detail.tmall.com'] def start_requests(self): 改变初始请求,根据自己的心意来 base_url = "https://detail.tmall.com/item.htm?spm=a220m.1000858.1000725.1.10071a2e3E99KN&id=576412995625&skuId=3959303342392&areaId=410881&standard=1&user_id=533497499&cat_id=50029231&is_b=1&rn=297f6b58b52879a5dd9d1a7b4d628f85" yield Request(url=base_url, callback=self.parse, dont_filter=True, meta={"page":"1"}) def parse(self, response): 进行解析 item = TmallItem() tr_list = response.xpath('//div[@class="rate-grid"]/table/tbody/tr').extract() for tr in tr_list: html = lxml.html.fromstring(tr) try: command = html.xpath('//div[@class="tm-rate-premiere"]/div[@class="tm-rate-content"]/div[@class="tm-rate-fulltxt"]/text()')[0] except: try: command = html.xpath('//div[@class="tm-rate-content"]/div[@class="tm-rate-fulltxt"]/text()')[0] except: command = "此用户暂无评价" times = html.xpath('//div[@class="tm-rate-date"]/text()')[0] try: explain = html.xpath('//div[@class="tm-rate-reply"]/div[@class="tm-rate-fulltxt"]/text()')[0] except: explain = "暂无店家解释" try: grade = html.xpath('//div[@class="rate-user-grade"]/p/text()')[0] except: grade = "普通会员" try: append_command = html.xpath('//div[@class="tm-rate-append"]/div[@class="tm-rate-content"]/div[@class="tm-rate-fulltxt"]/text()')[0] except: append_command = "暂无追加评论" item["command"] = command item["times"] = times item["explain"] = explain item["grade"] = grade item["append_command"] = append_command yield item yield Request(url="http://www.baidu.com",callback=self.parse,meta={"page": 2"}, dont_filter=True)
其实整个项目并不难,主要就是selenium的应用, 可以解决很多问题, 就是速度会很慢.
所以这些就不说了, 来看看咱们的切词, 得词云的过程
现在大家迫不及待了吧,那就直接上代码
想必大家看着有点蒙圈了吧,我来给大家分析一下吧
import pandas as pd import jieba.analyse import pymongo import matplotlib.pyplot as plt from wordcloud import WordCloud, ImageColorGenerator # 导入数据 首先导入你爬取的数据, 可以是txt文档, csv文档, 数据库 mg = pymongo.MongoClient('localhost', 27017).mine.tianmao 用pandas进行处理 data = pd.DataFrame(list(mg.find())) 拿到所有的评论内容 pl = data[:]["content"] pl_str = "" 拼接成字符串 for i in pl: pl_str += i
# 添加特定停止词 删掉一些无用的平时的修饰词,如'的''啦'等 jieba.analyse.set_stop_words("stop_words.txt") # 基于TF-IDF算法进行关键词抽取 用TF-IDE算法对字符串进行切词, 得到所有的关键词 keywords = jieba.analyse.extract_tags(pl_str, topK=300,withWeight=True, allowPOS=('ns', 'n', 'vn', 'v')) # 'ns', 'n', 'vn', 'v' 即仅提取地名、名词、动名词、动词 # 基于TextRank算法进行关键词抽取 # keywords = jieba.analyse.textrank(pl_str, topK=10, withWeight=True, allowPOS=('ns', 'n', 'vn', 'v')) print(len(keywords)) # 词云图生成 cloud_con = '' for k, v in keywords: cloud_con += (k+"/")*(int(v*1000)) # bg_image = plt.imread('er.jpg')
#云图属性设置 wc = WordCloud(font_path="miaowu.ttf", 设置字体 background_color='white', 背景 width=800, 宽度 height=600, 高度 # mask=bg_image, max_font_size=166, 最大字体大小 min_font_size=16, 最小字体的尺度 max_words=1000, 词云容纳词量 mode='RGBA', # scale=2, # colormap='pink', collocations=False, random_state=30 ) wc.generate(cloud_con) # 设置字体颜色跟随背景变化 # bg_color = ImageColorGenerator(bg_image) # wc.recolor(color_func=bg_color) wc.to_file("word___cloud.png") plt.figure() plt.imshow(wc) # plt.axis("off") plt.show()
最后就来看看我们的辛苦结果吧
感觉怎么样, 都还喜欢嘛?有什么问题可以在下面评论哦! 我会在线上解答问题哦! 项目我也放到资源里了, 需要的可以去下载哦!
最后再加一句, 欢迎来评论交流哦!