昨天之所以水了,是因为日更30天了,歇一歇,同时也是为了完成今天的这个爬虫,毕竟第一次使用selenium+chrome爬取网站。

前两天写分析ajax爬虫,是分析了网站请求的参数、请求地址、上传的表单,模拟浏览器访问页面来的到源码,但是有时候ajax的参数非常多,而且经过加密,很难找到规律。这时候我们就需要使用selenium这个强大的库了,它可以控制浏览器,模拟人的操作,直接获取浏览器渲染完成后的页面源码,真正做到可见即可爬。

不多说,让我们开始吧!
selenium需要我们配合浏览器使用,它支持很多款浏览器,但是我更喜欢chrome,因为它调试起来更方便,就像很多前段程序猿也喜欢chrome一样,反正我不喜欢IE,让它当场去世吧!

chromeDriver 也是必需品。下载下来后放在环境的script文件下。

这次也是,还是剩下一小部分没完成,现在还没学习到。之后会完善。

  • 搜索商品后会直接跳到登录界面,所以我直接打开的登录界面,现在我只能扫码登陆,账号密码登陆会出滑动验证码,这在ChromeDriver里无法完成,我就直接等10s让我扫码登陆了。

其实吧我感觉爬虫没什么好讲的,主要是对抗反爬机制能够给我带来快乐。这次淘宝的反爬很厉害。换页的速度不能太快,太快的话,到18页就会被要求进行滑动验证,但是由于浏览器问题,总是失败。所以我在换页之前用了10s的延时才能全部爬下来。

一共爬了100页,我输入的‘ipad’,一共4404条数据,全部存在数据库中,方便以后使用:

image.png
结果

[图片上传失败…(image-e5e97b-1553952994597)]

这次的程序中设计等待时间的概念,一个是隐式等待,一个是显示等待。
隐式等待就是等待给定的时间,在寻找页面中的元素,如果时间到了还没加载出来,就报错,这一般用的少,但这次我也用了,在扫码登录的时候。
显示等待是指如果再规定的时间内加载出来了,就获取节点,如果没有加载出来报错。

代码不长,具体内容就不讲了,没意思。你爬虫遇到问题了,来对比下,找找不同,这样才能得到最大的进步,什么都直接说出来,就没有找答案的这个过程,也就没有任何的成就感,而且我写这个,只是我为了记录自己的学习过程。最终虽然得到了我想要的,但反爬机制没解决,感觉得到之后一切都变得索然无味。

还有就是浏览器滑动验证这一点,这将是我接下来的学习方向,之后就可以为所欲为了。

import re
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from pyquery import PyQuery as pq
from config import *
import pymongo

# chrome_options = webdriver.ChromeOptions()
# chrome_options.add_argument()
browser = webdriver.Chrome()

wait = WebDriverWait(browser, 10)
client = pymongo.MongoClient(MONGODB_HOST, MONGODB_POST)
db = client[MONGODB_DB]
collection = db[MONGODB_COLLECTION]

def login():
    print("正在登录")
    # 需要用手机淘宝扫二维码登录才能搜索
    browser.get(url='https://login.taobao.com')
    # 10s用来扫码登录
    browser.implicitly_wait(10)

def search():
    print("正在查找",KEYWORD)
    try:
        input = wait.until(
            EC.presence_of_element_located((By.CSS_SELECTOR, "#q"))
        )
        submit = wait.until(
            EC.element_to_be_clickable((By.CSS_SELECTOR, "#J_TSearchForm > div.search-button > button"))
        )
        input.send_keys(KEYWORD)
        submit.click()
        total = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,
                                                    "#mainsrp-pager > div > div > div > div.total")))
        get_goods()
        return total.text
    except TimeoutError:
        return search()

def next_page(page_number):
    print("正在换页", page_number)
    try:
        input = wait.until(
            EC.presence_of_element_located((By.CSS_SELECTOR, "#mainsrp-pager > div > div > div > div.form > input"))
        )
        submit = wait.until(
            EC.element_to_be_clickable(
                (By.CSS_SELECTOR, "#mainsrp-pager > div > div > div > div.form > span.btn.J_Submit"))
        )
        input.clear()
        input.send_keys(page_number)
        submit.click()
        wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR,
                                                     '#mainsrp-pager > div > '
                                                     'div > div > ul > '
                                                     'li.item.active > '
                                                     'span'), str(page_number)))
        get_goods()
    except Exception:
        next_page(page_number)


def get_goods():
    try:

        wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,
                                                   '#mainsrp-itemlist .items '
                                                   '.item')))
        html = browser.page_source
        doc = pq(html)
        items = doc('#mainsrp-itemlist .items .item').items()
        for item in items:
            goods = {
                'img': item.find('.pic .img').attr('data-src'),
                'price': item.find('.price').text(),
                'deal': item.find('.deal-cnt').text(),
                'title': item.find('.title').text(),
                'shop': item.find('.shop').text(),
                'location': item.find('.location').text()
            }
            save_to_mongodb(goods)
    except Exception:
        print("获取商品失败")

def save_to_mongodb(result):
    try:
        if db[MONGODB_COLLECTION].insert_one(result):
            print("存储到数据成功", result)
    except Exception:
        print("存储到数据库失败", result)

def main():
    login()
    total = search()
    total = int(re.compile('(d+)').search(total).group(0))
    for i in range(2, total + 1):
        if i % 15 == 0:
            time.sleep(20)
        next_page(i)

if __name__ == '__main__':
    main()

在使用前一定要记得把该装的库都装了,数据库打开,网络通畅。

得抓紧学习了,要赶在工大春招之前学完。

之前在百度贴吧帮别人解决问题,这让我很开心,忘记了时间。所以今天晚了点。

文章来源于互联网:python爬虫08-selenium爬取淘宝网商品(源码)

发表评论