避踩雷 | 爬取美团门店信息中的“量子幽灵”
【摘要】 美团爬虫其实很早就有写过,除了薛定谔的验证码,其他的都还蛮好解决滴~为什么会单独开一个帖子呢,主要是因为做【不秃头 | 如何用ModelArts满足一个奶茶重度爱好者的好奇心】的时候需要用到美团里奶茶门店的数据,其中获取的时候遇到了一些问题,虽然最后解决了,但还是碰了许多壁,便想着记录下来,免得其他小伙伴大伙伴们又被这个奇怪的问题卡住辽~
美团爬虫其实很早就有写过,除了薛定谔的验证码,其他的都还蛮好解决滴~为什么会单独开一个帖子呢,主要是因为做【不秃头 | 如何用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
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
作者其他文章
评论(0)