目的:按给定关键词爬取京东商品信息,并保存至mongodb。

字段:title、url、store、store_url、item_id、price、comments_count、comments

工具:requests、lxml、pymongo、concurrent

分析:

1.  https://search.jd.com/Search?keyword=耳机&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&wq=er%27ji&page=1&s=56&click=0,这是京东搜索耳机的跳转url,其中关键参数为:

 keyword:关键词

 enc:字符串编码

 page:页码,需要注意的是,这里的数值均为奇数

 所以简化后的 url 为 https://search.jd.com/Search?keyword=耳机&enc=utf-8&page=1

2.  分析各字段的 xpath,发现在搜索页面只能匹配到 title、url、store、store_url、item_id、price。至于 comments_count、comments 需要单独发出请求。

3.  打开某一商品详情页,点击商品评价,打开开发者工具。点击评论区的下一页,发现在新的请求中,除去响应为媒体格式外,仅多出一个 js 响应,故猜测评论内容包含其中。

4.  分析上述请求的 url,简化后为 https://sclub.jd.com/comment/productPageComments.action?productId=100004325476&score=0&sortType=5&page=0&pageSize=10,其中:

 productId:商品的Id,可简单的从详情页的 url 中获取

 page:评论页码

5.  由以上可以得出,我们需要先从搜索页面中获取的商品 id,通过 id 信息再去获取评论信息。爬取评论时需要注意,服务器会判断请求头中的 Referer,即只有通过商品详情页访问才能得到评论,所以我们每次都根据 item_id 构造请求头。

6.  先将基础信息插入至数据库,在得到评论信息后,根据索引 item_id 将其补充完整。

代码:

 import requests
from lxml import etree
import pymongo
from concurrent import futures class CrawlDog:
def __init__(self, keyword):
"""
初始化
:param keyword: 搜索的关键词
"""
self.keyword = keyword
self.mongo_client = pymongo.MongoClient(host='localhost')
self.mongo_collection = self.mongo_client['spiders']['jd']
self.mongo_collection.create_index([('item_id', pymongo.ASCENDING)]) def get_index(self, page):
"""
从搜索页获取相应信息并存入数据库
:param page: 搜索页的页码
:return: 商品的id
"""
url = 'https://search.jd.com/Search?keyword=%s&enc=utf-8&page=%d' % (self.keyword, page)
index_headers = {
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,'
'application/signed-exchange;v=b3',
'accept-encoding': 'gzip, deflate, br',
'Accept-Charset': 'utf-8',
'accept-language': 'zh,en-US;q=0.9,en;q=0.8,zh-TW;q=0.7,zh-CN;q=0.6',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/74.0.3729.169 Safari/537.36'
}
rsp = requests.get(url=url, headers=index_headers).content.decode()
rsp = etree.HTML(rsp)
items = rsp.xpath('//li[contains(@class, "gl-item")]')
for item in items:
try:
info = dict()
info['title'] = ''.join(item.xpath('.//div[@class="p-name p-name-type-2"]//em//text()'))
info['url'] = 'https:' + item.xpath('.//div[@class="p-name p-name-type-2"]/a/@href')[0]
info['store'] = item.xpath('.//div[@class="p-shop"]/span/a/text()')[0]
info['store_url'] = 'https' + item.xpath('.//div[@class="p-shop"]/span/a/@href')[0]
info['item_id'] = info.get('url').split('/')[-1][:-5]
info['price'] = item.xpath('.//div[@class="p-price"]//i/text()')[0]
info['comments'] = []
self.mongo_collection.insert_one(info)
yield info['item_id']
# 实际爬取过程中有一些广告, 其中的一些上述字段为空
except IndexError:
print('item信息不全, drop!')
continue def get_comment(self, params):
"""
获取对应商品id的评论
:param params: 字典形式, 其中item_id为商品id, page为评论页码
:return:
"""
url = 'https://sclub.jd.com/comment/productPageComments.action?productId=%s&score=0&sortType=5&page=%d&' \
'pageSize=10' % (params['item_id'], params['page'])
comment_headers = {
'Referer': 'https://item.jd.com/%s.html' % params['item_id'],
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/74.0.3729.169 Safari/537.36'
}
rsp = requests.get(url=url, headers=comment_headers).json()
comments_count = rsp.get('productCommentSummary').get('commentCountStr')
comments = rsp.get('comments')
comments = [comment.get('content') for comment in comments]
self.mongo_collection.update_one(
# 定位至相应数据
{'item_id': params['item_id']},
{
'$set': {'comments_count': comments_count}, # 添加comments_count字段
'$addToSet': {'comments': {'$each': comments}} # 将comments中的每一项添加至comments字段中
}, True) def main(self, index_pn, comment_pn):
"""
实现爬取的函数
:param index_pn: 爬取搜索页的页码总数
:param comment_pn: 爬取评论页的页码总数
:return:
"""
# 爬取搜索页函数的参数列表
il = [i * 2 + 1 for i in range(index_pn)]
# 创建一定数量的线程执行爬取
with futures.ThreadPoolExecutor(15) as executor:
res = executor.map(self.get_index, il)
for item_ids in res:
# 爬取评论页函数的参数列表
cl = [{'item_id': item_id, 'page': page} for item_id in item_ids for page in range(comment_pn)]
with futures.ThreadPoolExecutor(15) as executor:
executor.map(self.get_comment, cl) if __name__ == '__main__':
# 测试, 只爬取两页搜索页与两页评论
test = CrawlDog('耳机')
test.main(2, 2)

总结:爬取的过程中可能会被封 IP,测试时评论页面的获取被封锁,使用代理可以解决该问题,后面会来主要说一下代理的使用。

Python爬虫-爬取京东商品信息-按给定关键词的更多相关文章

  1. Java爬虫爬取京东商品信息

    以下内容转载于<https://www.cnblogs.com/zhuangbiing/p/9194994.html>,在此仅供学习借鉴只用. Maven地址 <dependency ...

  2. selenium模块使用详解、打码平台使用、xpath使用、使用selenium爬取京东商品信息、scrapy框架介绍与安装

    今日内容概要 selenium的使用 打码平台使用 xpath使用 爬取京东商品信息 scrapy 介绍和安装 内容详细 1.selenium模块的使用 # 之前咱们学requests,可以发送htt ...

  3. selenium+phantomjs爬取京东商品信息

    selenium+phantomjs爬取京东商品信息 今天自己实战写了个爬取京东商品信息,和上一篇的思路一样,附上链接:https://www.cnblogs.com/cany/p/10897618. ...

  4. python制作爬虫爬取京东商品评论教程

    作者:蓝鲸 类型:转载 本文是继前2篇Python爬虫系列文章的后续篇,给大家介绍的是如何使用Python爬取京东商品评论信息的方法,并根据数据绘制成各种统计图表,非常的细致,有需要的小伙伴可以参考下 ...

  5. python爬虫爬取京东、淘宝、苏宁上华为P20购买评论

    爬虫爬取京东.淘宝.苏宁上华为P20购买评论 1.使用软件 Anaconda3 2.代码截图 三个网站代码大同小异,因此只展示一个 3.结果(部分) 京东 淘宝 苏宁 4.分析 这三个网站上的评论数据 ...

  6. 简单的python爬虫--爬取Taobao淘女郎信息

    最近在学Python的爬虫,顺便就练习了一下爬取淘宝上的淘女郎信息:手法简单,由于淘宝网站本上做了很多的防爬措施,应此效果不太好! 爬虫的入口:https://mm.taobao.com/json/r ...

  7. 八个commit让你学会爬取京东商品信息

    我发现现在不用标题党的套路还真不好吸引人,最近在做相关的事情,从而稍微总结出了一些文字.我一贯的想法吧,虽然才疏学浅,但是还是希望能帮助需要的人.博客园实在不适合这种章回体的文章.这里,我贴出正文的前 ...

  8. 利用selenium爬取京东商品信息存放到mongodb

    利用selenium爬取京东商城的商品信息思路: 1.首先进入京东的搜索页面,分析搜索页面信息可以得到路由结构 2.根据页面信息可以看到京东在搜索页面使用了懒加载,所以为了解决这个问题,使用递归.等待 ...

  9. 正则爬取京东商品信息并打包成.exe可执行程序。

    本文爬取内容,输入要搜索的关键字可自动爬取京东网站上相关商品的店铺名称,商品名称,价格,爬取100页(共100页) 代码如下: import requests import re # 请求头 head ...

随机推荐

  1. Codeforces 1108F(克鲁斯卡尔的理解)

    最小生成树会多样的情况是:两个或多个边等长且连通同样的两个并查集块. 所以可以跑一遍克鲁斯卡尔,每次把当前等长的边数出来,注意不要边找边并查,因为有一部分边是正常跑生成树我们也不会要他的,这种直接跳了 ...

  2. 洛谷 P2261 [CQOI2007]余数求和 ||整除(数论)分块

    参考:题解 令f(i)=k%i,[p]表示不大于p的最大整数f(i)=k%i=k-[k/i]*i令q=[k/i]f(i)=k-qi如果k/(i+1)=k/i=qf(i+1)=k-q(i+1)=k-qi ...

  3. 基于webmagic的爬虫小应用

    以前没有写过爬虫程序,最近两天就研究了一下java的爬虫框架webmagic.然后写了一个demo 写爬虫的基本思想: 1.抓取目标连接 2.根据页面中标签,抓捕你需要的内容 3.保存结果集 以下是实 ...

  4. 访问TomCat出现的一些异常

    BUG-01:访问页面时出现: HTTP Status 500 servlet.init() for servlet DispatcherServlet threw exception...... 解 ...

  5. 关于ES6的Promise的使用深入理解

    ES6的promise对象研究 什么叫promise? Promise对象可以理解为一次执行的异步操作,使用promise对象之后可以使用一种链式调用的方式来组织代码:让代码更加的直观. 那我们为什么 ...

  6. P2712 摄像头

    题目描述 食品店里有n个摄像头,这种摄像头很笨拙,只能拍摄到固定位置.现有一群胆大妄为的松鼠想要抢劫食品店,为了不让摄像头拍下他们犯罪的证据,他们抢劫前的第一件事就是砸毁这些摄像头. 为了便于砸毁摄像 ...

  7. 基于 Web 的 Go 语言 IDE - Wide 1.5.0 发布!

    Wide 是什么 Wide 是一个基于 Web 的 Go 语言团队 IDE. 在线开发:打开浏览器就可以进行开发.全快捷键 智能提示:代码自动完成.查看表达式.编译反馈.Lint 实时运行:极速编译. ...

  8. ZooKeeper读书笔记

    <ZooKeeper读书笔记> 1.Zookeeper是什么?Zookeeper是一个典型的分布式数据一致性的解决方案,分布式应用可以基于它实现诸如数据发布/订阅.负载均衡.命名服务.分布 ...

  9. Redis学习笔记(五)散列进阶

    HEXISTS key_name key(检查键key是否存在) HKEYS key_name(获得散列的所有键) HVALS key_name(获得散列的所有值) HINCRBY key_name ...

  10. 再遇BGP

    第一次遇到BGP,是在大学的课堂上,现在再次看到它,有种深深的无奈,我只记得它的名字,忘记了它的样子. 那么什么是BGP呢? 翻译过来就是边界网关协议,一个用来网络数据进行选路的路由协议,使用TCP协 ...