V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
samray
V2EX  ›  Python

从京东"窃取"150+万条数据 (爬虫)

  •  7
     
  •   samray ·
    ramsayleung · 2017-06-21 21:57:56 +08:00 · 9876 次点击
    这是一个创建于 2493 天前的主题,其中的信息可能已经有所发展或是发生改变。

    博客地址:从京东"窃取"150+万条数据

    github 地址: jd_spider

    使用 scrapy, scrapy-redis, graphite 实现的京东分布式爬虫,以 mongodb 实现底层存储。分布式 实现,解决带宽和性能的瓶颈,提高爬取的效率。实现 scrapy-redis 对进行 url 的去重 以及调度,利用 redis 的高效和易于扩展能够轻松实现高效率下载:当 redis 存储或者访问速 度遇到瓶颈时,可以通过增大 redis 集群数和爬虫集群数量改善

    爬取策略

    获取 <a href> 标签里面的 url 值,然后迭代爬取,并且把 url 限定在 xxx.jd.com 范围内,防止无限广度的问题。

    反爬虫策略

    禁用 cookie

    通过禁用 cookie, 服务器就无法根据 cookie 判断出爬虫是否访问过网站

    伪装成搜索引擎

    要说最著名的爬虫是谁?肯定是搜索引擎,它本质上也是爬虫,而且是非常强大的爬虫。 而且这些爬虫可以光明正大地去爬取各式网站,相信各式网站也很乐意被它爬。 现在可以通过修改 user-agent 伪装成搜索引擎

     'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)',
     'Mozilla/5.0 (compatible; Bingbot/2.0; +http://www.bing.com/bingbot.htm)',
     'Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)',
     'DuckDuckBot/1.0; (+http://duckduckgo.com/duckduckbot.html)',
     'Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)',
     'Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)',
     'ia_archiver (+http://www.alexa.com/site/help/webmasters; [email protected])',
    

    轮转 user-agent

    为了提高突破反爬虫策略的成功率,定义多个 user-agent, 然后每次请求都随机选择 user-agent。本爬虫实现了一个 RotateUserAgentMiddleware 类来实现 user-agent 的轮转

    代理 IP

    使用代理 IP, 防止 IP 被封

    爬虫状态监控

    将分布式爬虫 stats 信息(请求个数,item 下载个数,dropItem 个数,日志)保存到 redis 中 实现了一个针对分布式的 stats collector,并将其结果用 graphite 以图表形式动态实时显示

    并发请求和深度控制

    通过 setting.py 中的 CONCURRENT_REQUESTS = 32 配置来控制并发请求数量,通过 DepthMiddle 类的 DEPTH_LIMIT=max 参数来控制爬虫的的递归深度

    运行截图

    http://imgur.com/a/Q9Usi

    http://imgur.com/a/FBvay

    http://imgur.com/a/zgFWa

    第 1 条附言  ·  2017-06-22 15:54:57 +08:00

    谢谢大家的交流和提问,在交流期间我学到了很多新的想法 :).

    然后有同学对我 Github 上这个 Repo 好奇 (好奇害死猫呵),然后我就新发了一个主题来跟大家交流 浅谈Linux开发环境无缝迁移,  还有同学好奇我的博客. 我的博客是搭建在 github page上的,使用 Emacs org-mode 进行编写,在Emacs 里面编写,在 Emacs 里面发布.我是一个 Emacser :)

    87 条回复    2017-06-23 15:33:27 +08:00
    bozong
        1
    bozong  
       2017-06-21 22:13:30 +08:00 via iPhone
    屌屌屌。
    zhp521163
        2
    zhp521163  
       2017-06-21 22:16:31 +08:00
    很猛!
    shiny
        3
    shiny  
       2017-06-21 22:17:34 +08:00
    代理 ip 用的是哪一家?
    samray
        4
    samray  
    OP
       2017-06-21 22:18:35 +08:00
    欢迎大家不吝指教.
    bozong
        5
    bozong  
       2017-06-21 22:21:31 +08:00
    同问。代理 IP 来源
    samray
        6
    samray  
    OP
       2017-06-21 22:21:41 +08:00   ❤️ 1
    代理 IP 用的不是一家,是用这两位的项目  https://github.com/qiyeboy/IPProxyPool   https://github.com/qiyeboy/IPProxyPool .只是个人感觉还是不够方便,还需要自己安装和配置环境,所以我就把这两个项目做成 docker image. 然后映射  IP 出来,通过  api 获取代理 IP. 只是 image 还有点问题,所以还没有分享出来.
    xiaoyu9527
        7
    xiaoyu9527  
       2017-06-21 22:22:23 +08:00
    爬虫监控状态这个是怎么做的。

    感觉很屌。
    bozong
        8
    bozong  
       2017-06-21 22:23:42 +08:00
    NB
    samray
        9
    samray  
    OP
       2017-06-21 22:25:53 +08:00
    主要是将 scrapy.spider 的 stats 保存到 Redis (单机或者是集群),然后通过将这些数据发送给 graphite 来生成监控动态图.主要参考  https://github.com/gnemoug/distribute_crawler  的做法.只是这个项目已经没有维护了,并且是 python2,所以要自己看源码做一些适配.
    Thoxvi
        10
    Thoxvi  
       2017-06-21 22:27:37 +08:00 via Android
    反反爬虫策略…?
    samray
        11
    samray  
    OP
       2017-06-21 22:29:13 +08:00
    此外,graphite 的配置安装是很麻烦的事情,并且是不支持 windows  (虽说我是 Linuxer), 所以用 docker 就非常方便.我自己就在别人做好的  graphite 基础上做了些许配置的修改然后生成新的 image 适配 scrapy+graphite
    samray
        12
    samray  
    OP
       2017-06-21 22:30:13 +08:00   ❤️ 1
    突破反爬虫策略嘛,所以就叫反反爬虫策略.见笑了.
    bozong
        13
    bozong  
       2017-06-21 22:32:26 +08:00
    @samray #9 用了多少台机器在爬
    fate0
        14
    fate0  
       2017-06-21 22:47:35 +08:00
    代理部分,下次可以试试我写的代理程序 [https://www.v2ex.com/t/369905]( https://www.v2ex.com/t/369905) (。・`ω´・)
    samray
        15
    samray  
    OP
       2017-06-21 22:56:00 +08:00
    一台 32Gb 内存的工作站,跑了三个实例.
    samray
        16
    samray  
    OP
       2017-06-21 23:01:33 +08:00
    @fate0 其实主要的问题是免费的代理大部分都不能用,而且即使现在能用,下一分钟也可能不能用.并且以文本形式来存储代理 IP,在运行的时候将代理 IP 全部加载进内存,但是如果你的爬虫是长时间运行,代理应该很快用完.所以比较理想的是"动态"加载代理 IP. 即可以在运行时继续加载 IP. 个人小小的看法.也很感谢你的项目啦 :)
    fate0
        17
    fate0  
       2017-06-21 23:18:35 +08:00
    @samray readme 里说可以全加载到内存,只不过想体现这个程序的方便而已,我个人喜欢把所有的代理都放在 redis 里,每间隔 15min 就把 proxylist 拉下来换一批,2000+个代理,15min 内一般项目一般都够用了,用 proxylist 的优点是自己不用再维护一个 proxy pool, 缺点是没法给每个 proxy 打分统计、proxylist 上的代理,可能在某个地区没法使用。
    samray
        18
    samray  
    OP
       2017-06-21 23:22:55 +08:00
    其实最大的问题是,知道这一刻的代理可用,但是却完全没办法保证下一刻依旧可用.:(
    misaka19000
        19
    misaka19000  
       2017-06-21 23:24:18 +08:00
    不错,准备学习一个!
    fate0
        20
    fate0  
       2017-06-21 23:27:03 +08:00
    @samray 这不算什么问题吧,出现 exception 就换下一个代理,商业代理偶尔也有抽风的时候,也会出现下一刻不可用,就看换代理的频率是不是可以接收的范围内。
    supman
        21
    supman  
       2017-06-22 00:04:58 +08:00
    休斯顿的?
    xingzhi
        22
    xingzhi  
       2017-06-22 00:46:18 +08:00
    关键还是在于代理。
    Thoxvi
        23
    Thoxvi  
       2017-06-22 01:11:27 +08:00 via Android
    @samray

    不我的意思是似乎少打字了…
    samray
        24
    samray  
    OP
       2017-06-22 06:56:38 +08:00
    @Thoxvi README 上面已经修改,但是 V2EX 就没办法修改 :(
    samray
        25
    samray  
    OP
       2017-06-22 07:00:53 +08:00
    @fate0 我是用这个中间件来管理代理 IP 的  https://github.com/aivarsk/scrapy-proxies,随机选择代理 IP,不可用就把代理 IP 丢了. 只是还是会出现运行到一段时间之后,代理 IP 全部被丢完的情况
    samray
        26
    samray  
    OP
       2017-06-22 07:05:05 +08:00
    @supman 不太懂你表达的意思?
    gaohigh
        27
    gaohigh  
       2017-06-22 08:00:38 +08:00
    厉害了,屌屌
    cxh116
        28
    cxh116  
       2017-06-22 08:07:43 +08:00 via Android
    天猫难抓,禁止蜘蛛,无 cookie 直接重定向到登录页添加 cookie.
    yongliang
        29
    yongliang  
       2017-06-22 08:45:42 +08:00
    不错不错,马克下
    vipwpcom
        30
    vipwpcom  
       2017-06-22 08:50:22 +08:00
    二话不说,丢个星
    fate0
        31
    fate0  
       2017-06-22 09:02:38 +08:00
    @samray https://github.com/aivarsk/scrapy-proxies 这代码也是从一个文本读内容啊,完全可以自己实现一个 download middleware 从 redis 里取。
    Arrowing
        32
    Arrowing  
       2017-06-22 09:24:42 +08:00 via Android
    666666,感谢楼主科普
    HuangLibo
        33
    HuangLibo  
       2017-06-22 09:29:31 +08:00
    分布式爬虫, 看起来很好玩, 赶紧给个星
    RubyJack
        34
    RubyJack  
       2017-06-22 09:31:30 +08:00
    https://36kr.com/p/5078918.html 你的爬虫会把自己送进监狱吗?
    figofuture
        35
    figofuture  
       2017-06-22 09:41:32 +08:00
    mark
    ajan
        36
    ajan  
       2017-06-22 09:49:34 +08:00
    按 2017 年 6 月 1 日,《网络安全法》以及最新刑事司法解释:

    未经授权爬取用户手机通讯录超过 50 条记录,老板进去最高可达 3 年

    未经授权抓取用户淘宝交易记录超过 500 条的,老板进去最高可达 3 年

    未经授权读取用户运营商网站通话记录超过 500 条以上的,老板进去最高可达 7 年

    未经授权读取用户公积金社保记录的超过 50000 条的,老板进去最高可达 7 年
    samray
        37
    samray  
    OP
       2017-06-22 09:52:35 +08:00
    @cxh116 爬取难度 淘宝>天猫>京东.淘宝的反爬实在太强.即使用上我提到的所有反反爬虫策略.半个小时内就会爬不动,即使爬取频率不高.
    samray
        38
    samray  
    OP
       2017-06-22 09:53:34 +08:00
    @ajan 只是爬取商品信息和商品评论,并未涉及到交易记录.
    fiht
        39
    fiht  
       2017-06-22 09:57:10 +08:00
    我后来才知道,没有调度功能的爬虫在某种意义上来说不算是分布式爬虫...
    不过 redis 真的好用~~
    samray
        40
    samray  
    OP
       2017-06-22 09:58:51 +08:00
    @fate0 我知道,所以我之前提到的文本的代理 IP 会用尽就是我在爬虫过程中实际遇到的问题.可能我表达不够清晰,让你误解了.抱歉.其实我觉得爬虫的反反爬虫策略是一个问题.还有需要重点关注的是去重.之前我写的单机爬虫我都是用布隆过滤器来实现去重.只是这个项目是分布式的,用到 redis.就直接在 redis 去重.但是感觉效率没有布隆过滤器高.尤其是我这种直接从<a>标签中爬取 URL 的策略.去重就尤其重要.
    samray
        41
    samray  
    OP
       2017-06-22 10:08:51 +08:00
    @fiht 就 scrapy-redis 而言,因为用 redis 取代了 scrapy 自带的 collection.deque,就可以把需要爬取的队列从保存到内存中变成了保存到内存数据库中,但是这个时候,原来配置 collection.deque 使用的调度器就没办法使用了,也没办法进行分布式调度,于是 scrapy-redis 重写了 scrapy 的调度器.
    jccg90
        42
    jccg90  
       2017-06-22 10:15:34 +08:00
    哈,别老是欺负京东了。。。搞搞淘宝天猫的试试,感觉比京东的麻烦了很多
    xiaomeimei
        43
    xiaomeimei  
       2017-06-22 10:20:02 +08:00
    淘宝天猫阿里妈妈的那叫一个难爬。成功了几天又被封了
    samray
        44
    samray  
    OP
       2017-06-22 10:24:05 +08:00
    @jccg90 @xiaomeimei 淘宝天猫真的欺负不动.是被欺负 :(
    ayiis
        45
    ayiis  
       2017-06-22 10:25:23 +08:00
    大概有 10 天了?
    原来是你干的...
    Ixizi
        46
    Ixizi  
       2017-06-22 10:25:44 +08:00
    很强!
    bozong
        47
    bozong  
       2017-06-22 10:27:32 +08:00
    楼主,我们交个朋友吧
    samray
        48
    samray  
    OP
       2017-06-22 10:29:56 +08:00
    @ayiis 我干了什么好事?
    samray
        49
    samray  
    OP
       2017-06-22 10:31:01 +08:00
    @bozong 好啊.可以相互交流,相互学习嘛
    samray
        50
    samray  
    OP
       2017-06-22 10:33:10 +08:00
    @xiaomeimei 其实 QQ 空间也很难爬,想起我之前写的爬取 QQ 空间照片的爬虫. https://github.com/samrayleung/qzonePictureSpider .用了一个星期来解决登陆问题,还有需要根据 cookie 计算密钥.
    bozong
        51
    bozong  
       2017-06-22 10:38:04 +08:00
    @ayiis #45
    @samray #48 这位是京东运营团队
    myself659
        52
    myself659  
       2017-06-22 10:40:06 +08:00
    看一下评论,涨知识了
    samray
        53
    samray  
    OP
       2017-06-22 10:42:29 +08:00
    @ayiis 为京东引入流量 :)(不要打我)
    sunorg
        54
    sunorg  
       2017-06-22 10:49:48 +08:00
    @cxh116
    天猫的容易抓, 加个 cookie 头就行。


    速卖通的才难
    ayiis
        55
    ayiis  
       2017-06-22 10:53:13 +08:00
    @samray 套路啦
    cxh116
        56
    cxh116  
       2017-06-22 11:02:42 +08:00
    @sunorg 加 cookie 可以抓.但速度太难上去了,除非手上高质量代理 IP 多.
    vjnjc
        57
    vjnjc  
       2017-06-22 11:07:20 +08:00
    借楼问一下这个会触发最新的 gov 的爬虫策略吗?
    samray
        58
    samray  
    OP
       2017-06-22 11:29:32 +08:00
    并没有了解过..
    xiaomeimei
        59
    xiaomeimei  
       2017-06-22 11:57:07 +08:00
    @samray 直接用浏览器模拟呀
    suliuyes
        60
    suliuyes  
       2017-06-22 11:57:45 +08:00
    所有的爬虫,最核心最关键就是代理 ip 的问题,其他都不是事儿。
    tcpdump
        61
    tcpdump  
       2017-06-22 12:41:45 +08:00
    mark
    HGladIator
        62
    HGladIator  
       2017-06-22 12:54:55 +08:00 via iPhone
    我就卡在 IP 这块儿
    lanpong
        63
    lanpong  
       2017-06-22 13:10:23 +08:00
    github 上 README 的博客地址指向不对。。。
    samray
        64
    samray  
    OP
       2017-06-22 13:32:08 +08:00
    @lanpong 已经修改.谢谢你的建议.
    samray
        65
    samray  
    OP
       2017-06-22 13:34:57 +08:00
    @xiaomeimei 相信你指的应该是  PhantomJS  和  selenium  配合使用来模拟浏览器,但是这样对于爬虫来说实在太耗费资源了,相当于打开一个没有 GUI 的浏览器,然后解析需要爬取的页面.这个只能作为不是办法的办法了.
    samray
        66
    samray  
    OP
       2017-06-22 13:41:08 +08:00
    @suliuyes 其实,并不是那么绝对的,例如爬淘宝,即使你经常换代理 IP,也没办法突破它的反爬策略,因为爬虫无论怎么慢,对比人来说,操作都太快了.再比如爬取 QQ 空间,并不是简单的模拟请求登陆就可以了,再你登陆之后,服务器会在 cookie 中返回三个值 p_skey,skey,rv2,然后作移位和与或操作得到一个 gtk 值,然后每次请求都要附上这个 gtk 值,不然都是 403. 更不要说 Google 的人机检验机制,不是人类根本用不了.代理 IP 是一个关键点,但是并不是全部.如果你爬取的网页超过 1000 + w,光是去重就是一个值得深究的问题了.个人小小愚见 :)
    samray
        67
    samray  
    OP
       2017-06-22 13:47:48 +08:00
    附加一个个人推测,但未证实.在双11或者是 618 搞活动的时候,电商网站的反爬虫策略一般都会关闭,或者不会那么严格,因为面对洪峰一样的流量,需要把尽量多的资源用于处理客户端请求,而越复杂的反爬机制,需要的验证就越多,耗费的资源也会相应增加.不过这个只是个人主观感觉+合理推测,未证实.
    fate0
        68
    fate0  
       2017-06-22 14:16:05 +08:00
    @samray 1000+w 的数据去重也可以用 bloom filter 啊,就用 Redis 的 bitmap 存 bit 数组就可以了。
    shew2356
        69
    shew2356  
       2017-06-22 14:29:59 +08:00
    @ajan 第六十四条 网络运营者、网络产品或者服务的提供者违反本法第二十二条第三款、第四十一条至第四十三条规定,侵害个人信息依法得到保护的权利的,由有关主管部门责令改正,可以根据情节单处或者并处警告、没收违法所得、处违法所得一倍以上十倍以下罚款,没有违法所得的,处一百万元以下罚款,对直接负责的主管人员和其他直接责任人员处一万元以上十万元以下罚款;情节严重的,并可以责令暂停相关业务、停业整顿、关闭网站、吊销相关业务许可证或者吊销营业执照。
    违反本法第四十四条规定,窃取或者以其他非法方式获取、非法出售或者非法向他人提供个人信息,尚不构成犯罪的,由公安机关没收违法所得,并处违法所得一倍以上十倍以下罚款,没有违法所得的,处一百万元以下罚款。

    中华人民共和国网络安全法
    http://www.npc.gov.cn/npc/xinwen/2016-11/07/content_2001605.htm
    dallaslu
        70
    dallaslu  
       2017-06-22 14:33:46 +08:00
    我怎么记得京东基本不限制爬虫呢?
    samray
        71
    samray  
    OP
       2017-06-22 14:45:19 +08:00
    @fate0 在这个项目中,我是直接用 scrapy-redis 来,而 scrapy-redis 是把 request 的指纹保存起来进去去重的.只是感觉这样的做法不是很符合我自己的做法,因为就我看来,去重应该是直接对 url 去重.感觉这是不同的取舍,所以感慨一下.
    samray
        72
    samray  
    OP
       2017-06-22 14:50:09 +08:00
    @fate0 我倾向于使用的就是 bloomfilter,只是当变成分布式爬虫的时候,可能会因为分布式的设计不一样而导致不一样的问题出现.单机使用 bloomfilter 和分布式不一样,可以新建一个 master 节点,然后所有的需要爬取和已爬取的 url 都保存在 master,然后 slave 节点只需请求待爬 url 就好.但是这种方式不同于  scrapy-redis,就需要自己使用 bloomfilter 以及编写调度器
    fate0
        73
    fate0  
       2017-06-22 15:02:36 +08:00
    @samray 可能我说的不清楚,我现在说的就是分布式爬虫的情况,可以稍微修改一下 scrapy-redis 里的 dupefilter 文件,不使用之前 redis set 去重的方式,在这里改成使用 bloom filter,将 bloom filter 所使用的 bit 数组用 Redis 的 bitmap 进行存取。其他地方不需要修改。
    fate0
        74
    fate0  
       2017-06-22 15:04:06 +08:00
    @samray 另外使用整个 request 进行 hash 还是 只使用 url 进行 hash,也可以在 dupefilter 里修改,都不是特别难。
    samray
        75
    samray  
    OP
       2017-06-22 15:37:24 +08:00
    @fate0 抱歉,一直理解错了你的观点 :(
    doggg
        76
    doggg  
       2017-06-22 18:39:24 +08:00
    非常酷。这几天用 java 写 php 期末商城作业。只会一点 node 和 Jsoup 的我望而却步,最后还是死皮赖脸的跟图书馆老师要了全学校的图书馆数据。
    samray
        77
    samray  
    OP
       2017-06-22 19:23:31 +08:00
    @doggg 对于学校图书馆的网站,真的只会把网站爬崩,不会有反爬策略这种东西存在的.
    doggg
        78
    doggg  
       2017-06-22 20:15:27 +08:00
    @samray 平日泡图书馆比较多,跟老师比较熟。其实那个商城的数据本来想爬京东图书数据的,无奈不会 py,只会一点 node,而且图书分类获取非常麻烦,京东图书的分类太过于详细。所以跟老师要了图书馆所以的图书数据。总共 30W+
    dd0754
        79
    dd0754  
       2017-06-22 20:33:45 +08:00
    屌爆了
    MIROKY
        80
    MIROKY  
       2017-06-22 20:36:11 +08:00
    感谢分享 马上回去试试=w=
    binux
        81
    binux  
       2017-06-22 20:47:33 +08:00
    我一直认为随机 UA 就是个没卵用的东西
    一般选取的 UA 都是常见的,本身访问量很大的;多你爬虫几十万还是几百万根本没区别。
    如果对方能从某个 UA 的正常用户中分辨出爬虫,那么你换 UA,对方也能分辨出来。
    samray
        82
    samray  
    OP
       2017-06-22 21:13:08 +08:00
    @binux 这个并不能完全反反爬虫,只是可以提高突破的成功率.何况这个轮转操作并不是非常复杂和耗费资源,更何况我 UA 模拟的并不是正常用户,而是搜素引擎,搜索引擎本身也是爬虫.
    samray
        83
    samray  
    OP
       2017-06-22 21:14:42 +08:00
    @doggg 说明人脉有时候比技术好用 :)
    tausi0661
        84
    tausi0661  
       2017-06-23 09:09:14 +08:00
    @samray 我能羞羞的问问, 爬来了怎么卖钱?
    samray
        85
    samray  
    OP
       2017-06-23 09:25:37 +08:00
    @tausi0661 这.... 我写这爬虫只是用来分享,并未打算用于商业用途.商业用途就有待你发掘了,但是前提是遵守相关法规 :)
    SharkU
        86
    SharkU  
       2017-06-23 14:16:04 +08:00
    @samray 借楼问下,楼主最后破解了 QQ 空间吗?就是如果不使用 phantomjs。
    samray
        87
    samray  
    OP
       2017-06-23 15:33:27 +08:00
    @SharkU  最后我成功登陆并获取到 cookie,但是我是使用了 phantomjs 的,如果不使用的话,我折腾了一星期也不成功.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5281 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 38ms · UTC 06:01 · PVG 14:01 · LAX 23:01 · JFK 02:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.