欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python3 爬取并保存淘宝美食商品

程序员文章站 2022-05-28 23:25:16
...

main.py

import re
from selenium import webdriver  # 加载驱动
from selenium.common.exceptions import TimeoutException

# 下面三个包和等待页面加载完有关
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

from config import *
from pyquery import PyQuery as pq

import pymongo

# 使用谷歌浏览器驱动,需要1:安装了谷歌浏览器 2:有chromedriver_win32驱动并解压配置到环境变量中
# 他用的PhantomJS,不知道为什么提示错误
driver = webdriver.Chrome()
# 设定一个等待driver加载的时间,为10秒,超时就会不等了
wait = WebDriverWait(driver,10)
# 上面是一个显示等待的设置,详情请看:
# http://selenium-python.readthedocs.io/waits.html#explicit-waits

# 打开数据库客户端
client = pymongo.MongoClient(MONGO_URL)
# 选择某个数据库
db = client[MONGO_DB]

def search():
    print('searching')
    '''搜索关键字,并找到总的页数'''
    try:
        url = 'https://www.taobao.com/'
        # 用浏览器打开这个url
        driver.get(url)

        # 下面为不判断元素是否已经加载出来的版本# 可以对这两句稍微优化一下
        # input = driver.find_element_by_css_selector('#q')
        # submit = driver.find_element_by_css_selector('#J_TSearchForm > div.search-button > button')

        # 找到输入框元素,并等待加载完毕
        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')))
        # 得到的是'共 100 页,'
        # 这里要用正则把total.text的数字提取出来,因为group(0)好像就是原句,1才是切割出来的内容
        total = re.compile('(\d+)').search(total.text).group(1)
        return int(total)
    except TimeoutException:
        # 如果搜索超时,再找一遍
        search()

def next_page(page):
    try:
        print('now is page: ',page)
        # 找到输入页码的那个框
        input = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'#mainsrp-pager > div > div > div > div.form > input')))
        # 并找到翻页的那个按钮
        button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'#mainsrp-pager > div > div > div > div.form > span.btn.J_Submit')))
        # 不清空一下输入框,会混乱,因为原有的输入还没被清除,比如4之后输入5跳到45页
        input.clear()
        # 输入页码
        input.send_keys(page)
        # 点击翻页
        button.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)))
    except TimeoutException:
        return next_page(page)

def parse_page():
    print('parsing')
    # 等一下,把这个页中的商品完全加载出来再开始处理
    wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'#mainsrp-itemlist .items .item')))
    # 用pyQuery来处理html,类似的工具还有BeautifulSoup,lmxl或正则等
    # pq很像JQuery,基本上会JQuery就能学会这个
    # http://pythonhosted.org/pyquery/
    doc = pq(driver.page_source)
    # product: <class 'pyquery.pyquery.PyQuery'>
    # 一个生成器,导出所有找到的元素,即把每个商品放进生成器里面
    product = doc('#mainsrp-itemlist .items .item').items()
    # 遍历生成器,找到单个商品
    for item in product:
        # item: <class 'lxml.etree._Element'>
        # 用pyQuery提出各个标签中的信息
        # .是类的意思,#是ID,什么都没有就是标签名
        return  {
            # 浏览器没完全放大容易有换行符,统统去掉
            'title': item.find('.title').text().replace('\n',''),
            'price': item.find('.price').text().replace('\n',''),
            'shop': item.find('.shop').text().replace('\n',''),
            'location': item.find('.location').text().replace('\n',''),
            # 'image': item.find('.pic .img').attr('src').replace('\n',''),  # 图片,没什么用,个人喜好
            'url': 'http:' + item.find('.pic .pic-link').attr('href')
        }
        # print(result)

def save_to_mongo(result):
    try:
        # 把数据插入到meishi表中
        db[MONGO_TABLE].insert(result)
    except:
        print('存储出错')

def main():
    try:
        # 总页数
        total = search()
        # 先解析一下第一页吧
        result = parse_page()
        # 保存一下结果
        save_to_mongo(result)
        # 不需要从1开始了,起始页面就是1
        # for i in range(2,total):
        for i in range(2,5):
            # 开始翻页
            next_page(i)
            result = parse_page()
            save_to_mongo(result)
    except:
        print('某些地方出错了')
    finally:
        # 不管怎么样,出错或者跑完都把浏览器自动关了,避免占用太多内存
        driver.close()

if __name__ == '__main__':
    main()

config.py

# 定义一些变量,等下直接导入就好了
# 下面分别是host,数据库名,表名
MONGO_URL = 'localhost'
MONGO_DB = 'taobao'
MONGO_TABLE = 'meishi'
# 这个参数改一改就能爬其他的了
KEYWORD = '美食'


# 无页面的浏览器
# driver = webdriver.Chrome()
# PhantomJS的命令行参数,参考:
# http://phantomjs.org/api/command-line.html


运行结果

Python3 爬取并保存淘宝美食商品

数据库Python3 爬取并保存淘宝美食商品


相关标签: python3 爬虫