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
yeyu1989
V2EX  ›  Python

帮分析爬取一个网页信息 cn.investing.com

  •  
  •   yeyu1989 · 2017-11-20 22:59:43 +08:00 · 4701 次点击
    这是一个创建于 2560 天前的主题,其中的信息可能已经有所发展或是发生改变。
    https://cn.investing.com/stock-screener/?sp=country::37|sector::a|industry::a|equityType::a%3Ceq_market_cap;1

    如上,应该是用了很多 js,现在直接用 get 的方式,取到的股票记录数是 0
    用 post 的方式,{'sp','country::37|sector::a|industry::a|equityType::a%3Ceq_market_cap;1'}作为 data 输入也不行,得到的结果也是记录数是 0

    请问应该怎么解析这个网页?思路是什么?

    谢谢!
    16 条回复    2017-11-22 10:13:44 +08:00
    ospider
        1
    ospider  
       2017-11-20 23:10:21 +08:00 via iPad
    直接渲染出来页面啊
    qwjhb
        2
    qwjhb  
       2017-11-20 23:14:51 +08:00
    yeyu1989
        3
    yeyu1989  
    OP
       2017-11-21 08:17:52 +08:00 via Android
    @ospider 渲染页面是指啥?
    yeyu1989
        4
    yeyu1989  
    OP
       2017-11-21 08:45:30 +08:00 via Android
    @qwjhb 恕我刚入门,没有看懂关键点在哪儿。。下一步应该做什么?
    xiaobai987
        5
    xiaobai987  
       2017-11-21 09:07:11 +08:00
    @yeyu1989 用 py 模拟 post 请求啊
    raighne
        6
    raighne  
       2017-11-21 09:26:05 +08:00
    在 console 打$('#resultsTable tr')看看是不是你要的结果
    Marsss
        7
    Marsss  
       2017-11-21 09:27:49 +08:00
    1 楼和 2 楼都已经告诉你答案了,而且都是对的。1 楼的意思是直接使用 selenium 等自动化包驱动浏览器访问目标链接,浏览器运行 js 后渲染得到目标数据,具体实现搜索 selenium 相关知识点。

    2 楼的意思是分析 http 请求数据,发现目标数据实际是通过 XHR,带参数 POST 访问 https://cn.investing.com/stock-screener/Service/SearchStocks,直接得到数据。具体分析,可 F12 看 network 或者代理抓包。
    qwjhb
        8
    qwjhb  
       2017-11-21 09:42:20 +08:00   ❤️ 1
    @yeyu1989 你要的数据并不是在你写的那个网页里 而是载入网页后通过 api 调用获取的 api 的地址就是我上面写的这个 构造个一样的请求就能获得数据了
    建议找本爬虫的书看看 别跟视频教程学
    yeyu1989
        9
    yeyu1989  
    OP
       2017-11-21 09:55:47 +08:00
    @qwjhb
    data={'sp':'country::37|sector::a|industry::a|equityType::a<eq_market_cap;1'}
    header=func.randHeader()
    s = requests.post('https://cn.investing.com/stock-screener/Service/SearchStocks',params=data,headers=header)
    我这么写的,有什么问题吗?还是没有数据...
    yeyu1989
        10
    yeyu1989  
    OP
       2017-11-21 10:04:02 +08:00
    @qwjhb
    我现在都是照猫画虎,还没有系统学习过。想着边用边学来着
    qwjhb
        11
    qwjhb  
       2017-11-21 10:05:47 +08:00
    @yeyu1989 所以建议弄本书 快速的翻下其实更省时间
    qwjhb
        12
    qwjhb  
       2017-11-21 10:17:13 +08:00
    @yeyu1989 然后 data 不是你写的这些 f12 打开看看

    request 是这些内容

    POST /stock-screener/Service/SearchStocks HTTP/1.1
    Host: cn.investing.com
    Connection: keep-alive
    Content-Length: 909
    Accept: application/json, text/javascript, */*; q=0.01
    Origin: https://cn.investing.com
    X-Requested-With: XMLHttpRequest
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36
    Content-Type: application/x-www-form-urlencoded
    Referer: https://cn.investing.com/stock-screener/?sp=country::37|sector::a|industry::a|equityType::a|exchange::a%3Ceq_market_cap;1
    Accept-Encoding: gzip, deflate, br
    Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7,ja;q=0.6
    Cookie: PHPSESSID=tt0b1qp47ancp40619ftigb2t1; geoC=CN; adBlockerNewUserDomains=1511230139; StickySession=id.70178265937.000.cn.investing.com; adbBLk=6; billboardCounter_6=2; nyxDorf=Y2AxYmYuP2JkNWtgZCkxMjZnYj0%2BJzAzMDRlZw%3D%3D
    DNT: 1

    data 是这些

    country[]:37
    sector:2,11,7,10,1,4,9,5,8,3,6,12
    industry:63,85,82,21,10,86,7,78,36,25,4,28,67,5,71,27,61,90,23,68,34,89,43,50,81,41,56,59,69,9,83,29,52,100,58,95,102,94,60,53,38,87,31,6,16,48,55,74,66,35,65,40,99,42,92,98,39,70,32,45,77,20,54,33,24,72,51,30,64,2,96,8,14,22,26,80,15,37,93,13,46,1,79,44,75,91,49,62,88,12,47,84,57,76,17,97,18,19,3,11,101,73
    equityType:ORD,DRC,Preferred,Unit,ClosedEnd,REIT,ELKS,OpenEnd,Right,ParticipationShare,CapitalSecurity,PerpetualCapitalSecurity,GuaranteeCertificate,IGC,Warrant,SeniorNote,Debenture,ETF,ADR,ETC,ETN
    exchange[]:54
    exchange[]:103
    pn:1
    order[col]:eq_market_cap
    order[dir]:d
    yeyu1989
        13
    yeyu1989  
    OP
       2017-11-21 17:20:45 +08:00
    @qwjhb
    header={
    'Accept':'application/json, text/javascript, */*; q=0.01',
    'Accept-Encoding':'gzip, deflate, br',
    'Accept-Language':'zh-CN,zh;q=0.9',
    'Connection':'keep-alive',
    'Content-Length':'909',
    'Content-Type':'application/x-www-form-urlencoded',
    'Host':'cn.investing.com',
    'Origin':'https://cn.investing.com',
    'Referer':'https://cn.investing.com/stock-screener/?sp=country::37|sector::a|industry::a|equityType::a|exchange::a%3Ceq_market_cap;1',
    'User-Agent':'Opera/8.0 (Macintosh; PPC Mac OS X; U; en)',
    'X-Requested-With':'XMLHttpRequest'
    }
    data={
    'country[]':'37',
    'sector':'2,11,7,10,1,4,9,5,8,3,6,12',
    'industry':'63,85,82,21,10,86,7,78,36,25,4,28,67,5,71,27,61,90,23,68,34,89,43,50,81,41,56,59,69,9,83,29,52,100,58,95,102,94,60,53,38,87,31,6,16,48,55,74,66,35,65,40,99,42,92,98,39,70,32,45,77,20,54,33,24,72,51,30,64,2,96,8,14,22,26,80,15,37,93,13,46,1,79,44,75,91,49,62,88,12,47,84,57,76,17,97,18,19,3,11,101,73',
    'equityType':'ORD,DRC,Preferred,Unit,ClosedEnd,REIT,ELKS,OpenEnd,Right,ParticipationShare,CapitalSecurity,PerpetualCapitalSecurity,GuaranteeCertificate,IGC,Warrant,SeniorNote,Debenture,ETF,ADR,ETC,ETN',
    'exchange[]':'54',
    'exchange[]':'103',
    'pn':'1',
    'order[col]':'eq_market_cap',
    'order[dir]':'d'
    }
    session = requests.Session()
    s = session.post('https://cn.investing.com/stock-screener/Service/SearchStocks',params=data,headers=header)
    html = etree.HTML(s.text)

    我理解应该是这么写的?但还是得不到想要的结果...
    yeyu1989
        15
    yeyu1989  
    OP
       2017-11-22 09:53:16 +08:00
    @ospider @qwjhb @Marsss
    非常感谢各位大神,终于可以了。
    不过还有个小问题,就是 post 参数里的 pn:1,貌似只能得到第一页的 50 条记录,我试了一下好像只能一页一页的获取,要获取 70 多次。

    这种有什么简便的办法吗?
    noreason
        16
    noreason  
       2017-11-22 10:13:44 +08:00
    @yeyu1989 获取 70 多次对程序不是什么大的影响,不过就是不推荐用 selenium,因为它的访问相当于打开一个网页,会等网页全部渲染完才会执行下一步,效率低下.
    更推荐模拟 js 请求获取 json 数据的方式
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2539 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 15:28 · PVG 23:28 · LAX 07:28 · JFK 10:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.