爬虫pycharm(python)的selenium+pyquery+CSS选择器模拟浏览器爬取京东商品信息

准备工作:

库的安装::pip3 install selenium pip3 install pyquery
引入库与定义浏览器驱动对象:

from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from pyquery import PyQuery as pq
browser = webdriver.Chrome()
wait = WebDriverWait(browser,10)

在正式开始之前先解释一下接下来用到的几个常用表达:
1.显式等待wait.until,指定一个等待条件和最长等待时间,如果等待条件成立则立即返回,反之超过最长等待时间则抛出异常
2.presence_of_element_located:元素加载出,传入定位元组,如 (By.id,‘q’)
3.text_to_be_present_in_element:某个元素包含某文字
4.element_to_be_clickable:元素可点击

步骤流程

1.打开京东网站并模拟浏览器实现搜索功能
2.实现翻页功能
3.用CSS选择器爬取每一页商品的信息

1.模拟浏览器实现搜索功能

首先用browser打开京东官网并定位输入框的id
在这里插入图片描述
输入关键词python

        browser.get('https://www.jd.com/')
        input = browser.find_element_by_id('key')
        input.send_keys('python')

之前我们已经导入了类键盘库from selenium.webdriver.common.keys import Keys,可以使用Keys.ENTER回车按钮实现搜索功能

input.send_keys(Keys.ENTER)

同时我们还需要获取商品的总页数以实现接下来翻页次数的精确控制,打开搜索页面,定位最底部的共xx页中间的数字,复制选择器得到总页数
在这里插入图片描述

不要忘了设置处理异常,超时的话只要重新执行一次就可以了

def search():
    try:
        browser.get('https://www.jd.com/')
        input = browser.find_element_by_id('key')
        input.send_keys('python')
        input.send_keys(Keys.ENTER)
        total = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'#J_bottomPage > span.p-skip > em:nth-child(1) > b')))
        return total.text
    except TimeoutException:
        return 	search()

实现翻页功能

在正常访问网站中,翻页方式有两种,一种是点击下一页按钮实现翻页,另一种则是在输入框中输入页数点击确定进行翻页,对于第一种翻页而言,如果中途出现了错误不方便处理,于是我们选择在输入框里输入页数并点击确定实现该功能,也就是要实现一种循环操作

定位找到输入页数的方框和确认按钮,复制选择器

        input = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'#J_bottomPage > span.p-skip > input')))
        submit = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'#J_bottomPage > span.p-skip > a')))
        input.clear() #去掉当前输入框显示的数字
        input.send_keys(页码)
        submit.click()

为了判断当前所在的页面是否为期望得到的页面,我们需要加一个判断条件:当前页码是否高亮

wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR,'#J_bottomPage > span.p-num > a.curr'),str(页码)))

最后仍然不要忘记处理超时异常

def next_page(页码数):
    try:
        input = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'#J_bottomPage > span.p-skip > input')))
        submit = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'#J_bottomPage > span.p-skip > a')))
        input.clear()
        input.send_keys(each_page)
        submit.click()
        wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR,'#J_bottomPage > span.p-num > a.curr'),str(each_page)))
    except TimeoutException:
        next_page(页码数)

爬取商品信息

分析网页结构可以看到每一个商品都是一个classgl-item的标签,假如把每一个商品当做item的话,那么箭头所指的标签就是items,里面包含了该页面的所有商品,复制标签的选择器并用wait.until判断是否加载出来
在这里插入图片描述
接下来用pyquery得到源码

    wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#J_goodsList > ul')))
    html = browser.page_source
    doc = pq(html)
    items = doc('#J_goodsList > ul > li').items() #调用items方法可以得到所有选择的内容

接下来对每一个item爬取它的标题,价格以及店铺

    for item in items:
        price = item.find('.p-price').text()
        title = item.find('.p-name em').text().replace('\n','')
        sales = item.find('.p-shopnum a').attr('title')
        print(title,price,sales)

最后整理一下,得到总程序代码

from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from pyquery import PyQuery as pq
browser = webdriver.Chrome()
wait = WebDriverWait(browser,10)
def search():
    try:
        browser.get('https://www.jd.com/')
        input = browser.find_element_by_id('key')
        input.send_keys('python')
        input.send_keys(Keys.ENTER)
        total = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'#J_bottomPage > span.p-skip > em:nth-child(1) > b')))
        return total.text
        get_products()
    except TimeoutException:
        return search()
def next_page(each_page):
    try:
        input = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'#J_bottomPage > span.p-skip > input')))
        submit = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'#J_bottomPage > span.p-skip > a')))
        input.clear()
        input.send_keys(each_page)
        submit.click()
        wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR,'#J_bottomPage > span.p-num > a.curr'),str(each_page)))
        get_products()
    except TimeoutException:
        next_page(each_page)
def get_products():
    wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#J_goodsList > ul')))
    html = browser.page_source
    doc = pq(html)
    items = doc('#J_goodsList > ul > li').items() #调用items方法可以得到所有选择的内容
    for item in items:
        price = item.find('.p-price').text()
        title = item.find('.p-name em').text().replace('\n','')
        sales = item.find('.p-shopnum a').attr('title')
        print(title,price,sales)
def main():
    total = search()
    for i in range(2,int(total)+1):
        next_page(i)
if __name__ == '__main__':
    main()

最后放上一张效果图,因为我设置了10s等待的时间所以爬取比较慢,可以适当缩短时间在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值