python爬虫——用selenium爬取京东整站商品信息
1.先附上效果图(我偷懒只爬了4页)
2.京东的网址https://www.jd.com/
3.我这里是不加载图片,加快爬取速度,也可以用Headless无弹窗模式
options = webdriver.ChromeOptions()
options.add_experimental_option('prefs', {'profile.managed_default_content_settings.images': 2})
#不加载图片
browser = webdriver.Chrome(options=options)
wait =WebDriverWait(browser,50)#设置等待时间
url = 'https://www.jd.com/'
data_list = []#设置全局变量用来存储数据
keyword="python爬虫"#关键词
4.先找到搜索框并用selenium模拟点击(这里发现京东不需要登录就能看到商品信息)
def search():
browser.get('https://www.jd.com/')
try:
input = wait.until(
EC.presence_of_all_elements_located((By.CSS_SELECTOR, "#key"))
) #等到搜索框加载出来
submit = wait.until(
EC.element_to_be_clickable((By.CSS_SELECTOR, "#search > div > div.form > button"))
)#等到搜索按钮可以被点击
input[0].send_keys(keyword)#向搜索框内输入关键词
submit.click()#点击
total = wait.until(
EC.presence_of_all_elements_located(
(By.CSS_SELECTOR, '#J_bottomPage > span.p-skip > em:nth-child(1) > b')
)
)#记录一下总页码,等到总页码加载出来
html = browser.page_source#获取网页信息
prase_html(html)#调用提取数据的函数(后面才写到)
return total[0].text
except TimeoutError:
search()
5.进入了第一页,先写好翻页的函数,需要滑动到底部才能加载后30个商品,总共有60个商品
def next_page(page_number):
try:
# 滑动到底部
browser.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(random.randint(1, 3))#设置随机延迟
button = wait.until(
EC.element_to_be_clickable((By.CSS_SELECTOR, '#J_bottomPage > span.p-num > a.pn-next > em'))
)#翻页按钮
button.click()# 翻页动作
wait.until(
EC.presence_of_all_elements_located((By.CSS_SELECTOR, "#J_goodsList > ul > li:nth-child(30)"))
)#等到30个商品都加载出来
# 滑动到底部,加载出后三十个货物信息
browser.execute_script("window.scrollTo(0, document.body.scrollHeight);")
wait.until(
EC.presence_of_all_elements_located((By.CSS_SELECTOR, "#J_goodsList > ul > li:nth-child(60)"))
)#等到60个商品都加载出来
wait.until(
EC.text_to_be_present_in_element((By.CSS_SELECTOR, "#J_bottomPage > span.p-num > a.curr"), str(page_number))
)# 判断翻页成功,高亮的按钮数字与设置的页码一样
html = browser.page_source#获取网页信息
prase_html(html)#调用提取数据的函数
except TimeoutError:
return next_page(page_number)
6.能正常翻页就简单很多了,开始抽取需要的商品信息,搜索不同的关键词,页面的布局会有变化,需要重新写定位商品信息
def prase_html(html):
html = etree.HTML(html)
# 开始提取信息,找到ul标签下的全部li标签
try:
lis = browser.find_elements_by_class_name('gl-item')
# 遍历
for li in lis:
# 名字
title = li.find_element_by_xpath('.//div[@class="p-name p-name-type-2"]//em').text
# 价格
price = li.find_element_by_xpath('.//div[@class="p-price"]//i').text
# 评论数
comment = li.find_elements_by_xpath('.//div[@class="p-commit"]//a')
# 商铺名字
shop_name = li.find_elements_by_xpath('.//div[@class="p-shop"]//a')
if comment:
comment = comment[0].text
else:
comment = None
if shop_name:
shop_name = shop_name[0].text
else:
shop_name = None
data_dict ={}#写入字典
data_dict["title"] = title
data_dict["price"] = price
data_dict["shop_name"] = shop_name
data_dict["comment"] = comment
print(data_dict)
data_list.append(data_dict)#写入全局变量
except TimeoutError:
prase_html(html)
7.存储方法
def save_html():
content = json.dumps(data_list, ensure_ascii=False, indent=2)
#把全局变量转化为json数据
with open("jingdong.json", "a+", encoding="utf-8") as f:
f.write(content)
print("json文件写入成功")
with open('jingdong.csv', 'w', encoding='utf-8', newline='') as f:
# 表头
title = data_list[0].keys()
# 声明writer
writer = csv.DictWriter(f, title)
# 写入表头
writer.writeheader()
# 批量写入数据
writer.writerows(data_list)
print('csv文件写入完成')
8.封装接口方法:
1.请求方式:HTTP POST GET
2.公共参数:
名称 |
类型 |
必须 |
描述 |
key |
String |
是 |
调用key(必须以GET方式拼接在URL中) |
secret |
String |
是 |
调用密钥 (复制v:Taobaoapi2014 ) |
api_name |
String |
是 |
API接口名称(包括在请求地址中)[item_search,item_get,item_search_shop等] |
cache |
String |
否 |
[yes,no]默认yes,将调用缓存的数据,速度比较快 |
result_type |
String |
否 |
[json,jsonu,xml,serialize,var_export]返回数据格式,默认为json,jsonu输出的内容中文可以直接阅读 |
lang |
String |
否 |
[cn,en,ru]翻译语言,默认cn简体中文 |
version |
String |
否 |
API版本 |
3.请求代码示例,支持高并发请求(CURL、PHP 、PHPsdk 、Java 、C# 、Python...)
# coding:utf-8
"""
Compatible for python2.x and python3.x
requirement: pip install requests
"""
from __future__ import print_function
import requests
# 请求示例 url 默认请求参数已经做URL编码
url = "https://api-xixin.taobaoapi2014.cn/jd/item_get/?key=<您自己的apiKey>&secret=<您自己的apiSecret>&num_iid=10335871600"
headers = {
"Accept-Encoding": "gzip",
"Connection": "close"
}
if __name__ == "__main__":
r = requests.get(url, headers=headers)
json_obj = r.json()
print(json_obj)
4.响应示例
5.错误码说明