避踩雷 | 爬取美团门店信息中的“量子幽灵”
美团爬虫其实很早就有写过,除了薛定谔的验证码,其他的都还蛮好解决滴~为什么会单独开一个帖子呢,主要是因为做【不秃头 | 如何用ModelArts满足一个奶茶重度爱好者的好奇心】的时候需要用到美团里奶茶门店的数据,其中获取的时候遇到了一些问题,虽然最后解决了,但还是碰了许多壁,便想着记录下来,免得其他小伙伴大伙伴们又被这个奇怪的问题卡住辽~
目标:爬取北京市所有coco门店的奶茶图片和标签
也就是这一部分啦~
工具:python3.7 + selenium + Chrome79
在写爬虫的前几天(大概是4月中旬)Chrome自己悄悄更新辽~而selenium还不支持最新的Chrome,于是需要先整一个老版本的Chrome浏览器~(当然用其他家的浏览器也是阔以滴~)
为啥用selenium呢,因为不用配置各种奇奇怪怪的头部设置辽,一部分用JS生成的html代码也能够直接读到,而且当薛定谔的美团验证码出现时还可以直接手动输入~
(使用selenium前需要配置对应浏览器的webdriver,百度上太多辽就不写了~)
导入库的代码如下:
from selenium import webdriver import requests import time
step1:定位到北京市coco门店列表
打开美团官网,定位到搜索栏,输入搜索关键词“coco”,再点击右侧的搜索按钮,就能够进入门店列表~
代码如下:
driver = webdriver.Chrome() url = 'https://www.meituan.com/' driver.get(url) driver.find_element_by_xpath('//*[@id="main"]/header/div[2]/div[2]/div[1]/input').send_keys('coco') driver.find_element_by_xpath('//*[@id="main"]/header/div[2]/div[2]/div[1]/button/span').click()
有小伙伴可能会问,这个find_element_by_xpath意思是根据xpath定位元素我知道,后面这堆xpath路径你是怎么找的,总不能人工数吧?
当然不是,鼠标放到想要获取路径的元素上,单击右键——检查,在右侧找到目标元素,再单击右键——Copy——Copy XPath就阔以辽~(我使用的是Chrome,其他浏览器可能会有一些区别)
最后就会进入这样的界面
step2:采集每个门店的链接和“下一页”按钮的链接
检查源代码,发现整个门店列表都被很整齐滴封装在一个div里
打开其中一个div,链接就在里面
于是很方便地就能定位到每个链接并将他们保存起来,代码如下所示:
list = driver.find_element_by_class_name('common-list-main').find_elements_by_class_name('default-card') links = [] for l in list: link = l.find_element_by_tag_name('a').get_attribute('href') links.append(link)
接着就是找下一页的链接了
通过元素进行定位,发现它有一个很长的class属性right-arrow iconfont icon-btn_right,嗯,应该可以用它定位了。
测试运行,程序却提示没有定位到这个元素,于是我换了一个思路,首先定位到了这个页码列表,读取里面所有的a标签。
再取这个列表的最后一位,便成功实现了翻页。
代码如下:
driver.find_element_by_class_name('mt-pagination').find_elements_by_tag_name('a')[-1].click()
step3:采集每个门店主页中的奶茶图片和标签
进入页面之后,Chrome显示的是这个亚子~(请记住这一点,后面非常关键~)
定位到想要爬的元素,嗯,在一个列表里,挺好定位获取的应该~
结果没想到这里折腾了我好久…
首先想到的定位这个列表,再获取所有的li标签,在每个li标签里分别找到图片链接和图片标签,保存起来~结果发现定位不了。
那换个思路,反正每个门店里都只有6个图,那就直接for循环个6次,用xpath来定位~结果还是找不到这些元素。
难道是我元素定位方式有问题?试了试爬其他部分的信息,完全OK。
这下我彻底迷惑了~
正在纠结之时,忽然发现一个细节,在通过“检查”定位图片源代码时,第一次没有像其他元素那样直接定位在对应的源代码上,而是停在了那一大块的位置。再次点击“检查”,这才定位到目标位置。
难道?这个玩意是“量子态”的,必须要看到了才会出现,不看就没有吗?
于是我加上了一段滑动滚轮的代码,让网页从打开时的样子(即上面提到的那个亚子)变成下面这个样子~
然后再次运行爬虫,我惊奇地发现,它正常了!(真·量子态的图片栏)
附上这部分的代码~
js = 'window.open("%s");' % link driver.execute_script(js) windows = driver.window_handles driver.switch_to.window(windows[-1]) js = 'window.scrollTo(0,1000);' driver.execute_script(js) ul = driver.find_element_by_xpath('//*[@id="app"]/section/div/div[3]/div[1]/div[2]/div/ul') lis = ul.find_elements_by_tag_name('li') time.sleep(2)
step4:下载图片
最后一步便是根据爬取到的图片链接下载图片。
使用requests库进行图片的下载(基本操作,无需多说~)
代码如下:
pic_url = div.find_element_by_tag_name('img').get_attribute('src') tag = div.find_element_by_tag_name('span').text data = requests.get(pic_url).content with open('C:/Users/Sirius/Desktop/data/%s_%d.jpg' % (tag, n), 'wb') as f: f.write(data) print('已保存%s-%d' % (tag, n)) n += 1
一些细节
由于打开门店页面时会打开一个新的浏览器窗口,需要切换一下selenium的当前窗口,代码如下:
windows = driver.window_handles driver.switch_to.window(windows[-1])
同样,在爬取当前门店结束后需要关闭这个窗口,并切换回原来的那一个。
driver.close() windows = driver.window_handles driver.switch_to.window(windows[0])
2.保存文件时不能直接用标签,不然会把之前的图片给覆盖掉~
源代码
最后附上完整版的代码~
from selenium import webdriver import requests import time driver = webdriver.Chrome() url = 'https://www.meituan.com/' driver.get(url) driver.find_element_by_xpath('//*[@id="main"]/header/div[2]/div[2]/div[1]/input').send_keys('coco') driver.find_element_by_xpath('//*[@id="main"]/header/div[2]/div[2]/div[1]/button/span').click() n = 1 x = 0 while(x < 100): list = driver.find_element_by_class_name('common-list-main').find_elements_by_class_name('default-card') links = [] for l in list: link = l.find_element_by_tag_name('a').get_attribute('href') links.append(link) for link in links: try: js = 'window.open("%s");' % link driver.execute_script(js) windows = driver.window_handles driver.switch_to.window(windows[-1]) js = 'window.scrollTo(0,1000);' driver.execute_script(js) ul = driver.find_element_by_xpath('//*[@id="app"]/section/div/div[3]/div[1]/div[2]/div/ul') lis = ul.find_elements_by_tag_name('li') time.sleep(2) for div in lis: pic_url = div.find_element_by_tag_name('img').get_attribute('src') tag = div.find_element_by_tag_name('span').text data = requests.get(pic_url).content with open('C:/Users/Sirius/Desktop/data/%s_%d.jpg' % (tag, n), 'wb') as f: f.write(data) print('已保存%s-%d' % (tag, n)) n += 1 except Exception as e: print(e) driver.close() windows = driver.window_handles driver.switch_to.window(windows[0]) driver.find_element_by_class_name('mt-pagination').find_elements_by_tag_name('a')[-1].click() time.sleep(3) x += 1
- 点赞
- 收藏
- 关注作者
评论(0)