scrapy进阶《封号码罗》之如何优雅的获取网页JavaScript中的数据(www.amazon.co.uk)

免责声明:仅供学习,提高技术,请勿商业或恶意攻击网站等其他使用,欢迎留言,评论,点赞,转发!
由于亚马逊的机器检测比较灵敏,只能用scrapy+selenium来实现数据爬取了,虽然大部分的内容都能获取得到,比如静态的文字,可以直接获取了。如果想获取商品图片的高清大图,可能就没有那么容易了,一步一分析开始了
首先,得先找到高清图片的URL在哪儿吧,这个还是相对好找一些的,下图:
在这里插入图片描述
你会发现,data-old-hires属性不就是高清图片的URL地址吗,有了地址,获取图片不是近在咫尺吗?心中一阵狂喜。。。然而,左侧有四张图片,你才找到了一张,赶紧看看其他图片的高清地址,
咦?怎么其他图片难道没有高清地址
在这里插入图片描述
你准备放弃了,对不对,网页没有给数据,就是神仙,也拿不到啊?
别急,让我带你飞!
当你用鼠标,轻轻的滑过左侧四张缩略图时,右侧的li发生了变化
在这里插入图片描述
没错,我怀疑这是一个JS里面鼠标滑过的类似事件,那还等什么,有selenium怕什么,写鼠标滑动的操作呗,刚开始我就是这么操作的,但是效率是低的不能再低了,为什么呢?因为li出现是没有那么规律的,有时候是第四个开始,有时候又是第三个开始,那每一个不得搞try,下面是我之前写的代码:

    try:
        self.browser.get(request.url)
        # 点击左侧缩略图
        # slider = self.browser.find_element_by_css_selector("#nc_1_n1z")  # 找到滑动标签
        # X轴移动
        try:
            four = WebDriverWait(self.browser, 5).until(
                lambda x: x.find_element_by_xpath('//*[@id="altImages"]/ul/li[4]'))
            ActionChains(self.browser).click_and_hold(on_element=four).perform()
            for x in [0, 10, 20, 30, 40, 50, 50, 40, 30, 20, 10, 0]:
                ActionChains(self.browser).move_by_offset(xoffset=x, yoffset=0).perform()
            ActionChains(self.browser).release().perform()
        except Exception as e:
            print(e)
            try:
                four = WebDriverWait(self.browser, 5).until(
                    lambda x: x.find_element_by_xpath('//*[@id="altImages"]/ul/li[1]'))
                ActionChains(self.browser).click_and_hold(on_element=four).perform()
                for x in [0, 10, 20, 30, 40, 50, 50, 40, 30, 20, 10, 0]:
                    ActionChains(self.browser).move_by_offset(xoffset=x, yoffset=0).perform()
                ActionChains(self.browser).release().perform()
            except Exception as e:
                print(e)
        # Y轴移动
        try:
            three = WebDriverWait(self.browser, 5).until(
                lambda y: y.find_element_by_xpath('//*[@id="altImages"]/ul/li[3]'))
            ActionChains(self.browser).click_and_hold(on_element=three).perform()
            for y in [0, 10, 20, 30, 40, 50, 50, 50, 40, 30, 20, 10, 0]:
                ActionChains(self.browser).move_by_offset(xoffset=0, yoffset=y).perform()
            ActionChains(self.browser).release().perform()
        except Exception as e:
            print(e)
            try:
                three = WebDriverWait(self.browser, 5).until(
                    lambda y: y.find_element_by_xpath('//*[@id="altImages"]/ul/li[4]'))
                ActionChains(self.browser).click_and_hold(on_element=three).perform()
                for y in [0, 10, 20, 30, 40, 50, 50, 50, 40, 30, 20, 10, 0]:
                    ActionChains(self.browser).move_by_offset(xoffset=0, yoffset=y).perform()
                ActionChains(self.browser).release().perform()
            except Exception as e:
                print(e)
    except TimeoutException as e:
        print("timeout")
        self.browser.execute_script("window.stop()")

眼明手快的老铁可能已经发现了,分了X轴和Y轴,这是因为要模拟鼠标滑过这些缩略图,而这些缩略图,有的是在左侧竖着排列,有的是在底部横着排列,所以,要写不同的try,不同的try又对应起始不同的li标签,所以,大概有四分之三的步骤是在浪费时间,只有正确的四分之一的操作对应到了某个商品,如果爬取少量的数据,这玩意儿也差不多,但是要几千几万的爬,这效率就低太多了,难道就没有更效率的方法了吗?唉,头发好像就少了一些。。。
重新回到页面,继续分析,验证猜测,
在这里插入图片描述
翻遍了所有的请求,最后还是发现并猜想,既然这些数据没有异步加载,而是直接返回了数据,可能高清图片地址就隐藏在某个js里面,只不过需要鼠标滑过去触发才能显示,
在这里插入图片描述
因为之前写过几个亚马逊的爬虫,所以我清楚的之后,亚马逊的图片命名有一个规律,那就是相同商品高清图片地址像素的大小相同,切后缀是统一的,所以我打算搜索一下._AC_SL1000_.jpg检测一下我的猜想
在这里插入图片描述
果然,天无绝人之路,数据已经在响应里面了,而且经过前后分析,我发现数据就是在这个方法里面,那我又该通过什么方式获取这些数据呢?
回到页面,重新搜索一下,看看数据在不在标签里面,xpath能搞不能?
在这里插入图片描述
开心一刻!
在这里插入图片描述
xpath能拿到数据了,但是需要的高清图地址又该怎么获取呢?有头绪吗?冥想中。。。
管他三七二十一,先把获取到的数据打印出来看一看再说:

hdimg_js_str = response.xpath('//*[@id="imageBlock_feature_div"]/script[1]/text()').extract_first()

是不是发现,打印出来的数据,还是跟网页上面的一样,一行一行的,还有空格和换行呢?这该怎么搞呢?
还能怎么办,整理数据呗!

hdimg_js_str = str(hdimg_js_str).replace(" ", "").replace("\n", "").replace("\r", "")

嗯嗯,这是一个大的字符串,我需要的数据在哪儿呢?
在这里插入图片描述
数据已经能够拿到了,要提炼出来高清图地址,看来只能拿出我的re来获取了,反反复复的尝试:把当前四个数据正则出来很简单,回头一想,不同的商品有不同数量的图片,那就是正则直接从字符串中获取图片地址就不科学了,你用match,search,findall,哪个都不合适呀,怎么办,怎么办?
咦,数据在colorImages字典里面,我可以先用正则获取这个大字典的字符串,然后转成字典,遍历字典应对不同数量的图片地址,这种方式它不香吗,搞起来。。。
先正则获取字典字符串:

reg = re.compile(".*data.*({\'colorImages\'.*),\'colorToAsin\'.*")
hdimg_str = reg.search(hdimg_js_str).group(1)

这样,就能获取到里面colorImages的字符串了,现在,需要把它改造成一个字典的样子,

hdimg_str = str(hdimg_str).replace("'", "\"") + "}"

现在它已经是一个字典样子的字符串了,那怎样才能把一个字符串转变成一个字典呢?json就该出马了

hdimg_dict = json.loads(hdimg_str, encoding="utf-8")

打印一下试试,一个字典也是一个json,那获取数据不要太舒服了,

hdimgs = ""  # 定义一个空字符串,用于存储图片地址
for img_url in hdimg_dict["colorImages"]["initial"]:
  	hdimgs = hdimgs + img_url["hiRes"] + " | "
# 去除最后多出来的空格和竖线符号
main_hdimgs = hdimgs[:-3]
item["main_hdimgs"] = main_hdimgs

这样一来,selenium里面的那些try用来模拟鼠标滑动的语句就都可以删除了,只用它打开页面,加载完之后直接返回数据就可以了。

try:
    self.browser.get(request.url)
    self.browser.execute_script('window.scrollTo(0, 300)')
except TimeoutException as e:
    print("timeout", e)
    self.browser.execute_script("window.stop()")
time.sleep(random.random() * 1)
return HtmlResponse(url=self.browser.current_url, body=self.browser.page_source, encoding="utf-8",
                        request=request)

最后,来一组爬取好的数据镇楼!
在这里插入图片描述

如果有什么问题,VX:gcw-410,昵称:浅情人不知

发布了30 篇原创文章 · 获赞 5 · 访问量 3325

猜你喜欢

转载自blog.csdn.net/Python_DJ/article/details/103984813