Python爬虫—简书首页数据抓取

作者: loading_miracle | 来源:发表于2017-05-24 10:46 被阅读1287次
    简书

    本该昨天完成的文章,拖了一天。可能是没休息好吧,昨天的在思路以及代码处理上存在很多问题,废话不多说,我们一起来看一下简书首页数据的抓取。

    抓取的信息

    2.2)简书首页文章信息 http://www.jianshu.com/
    包括:标题,作者,发表时间,阅读量,评论数,点赞数,打赏数,所投专题

    字段位置

    单页数据的获取

    我们先简单看一下单页数据的抓取,所谓单页就是我们最少能获取到的数据,那么我们就先去看一下这些信息的的加载方式

    检查工具

    通过工具我们可以看到有一个请求连接,接着我们去看一下数据

    信息详情

    这些信息跟我们要抓取的没任何关系,那我们就可以直接从源码中找这些信息了

    数据
    通过分析我们看到每一个li标签包含我们要抓取的所有信息的信息,那就可以以这个为循环点,解析第一个页面(xpath,或者通过Beautifulsoup),这里我选择的是xpath,我遇到了一个问题,就是评论数和阅读量通过xpath抓不到(可能是路径问题),我是通过正则去获取了这两个信息,下面给部分单页信息获取源码
        def getData(self,url):
            print url
            html = requests.get(url,headers = self.headers,cookies = self.cookies).text
            response = etree.HTML(html)
            item = {}
            flag = 0
            read = re.findall(r'ic-list-read"></i> (\d+)', html)
            comment = re.findall(r'ic-list-comments"></i> (\d+)', html)
            result = response.xpath('//*[@id="list-container"]/ul/li/div')
            for one in result:
                item[1] = one.xpath('a/text()')[0]
                item[2] = one.xpath('div[1]/div/a/text()')[0]
                item[3] = one.xpath('div[1]/div/span/@data-shared-at')[0]
                item[4] = read[flag]
                try:
                    item[5] = comment[flag]
                except:
                    item[5] = u''
                item[6] = one.xpath('div[2]/span/text()')[0].strip()
                try:
                    item[7] = one.xpath('div[2]/span[2]/text()')[0].strip()
                except:
                    item[7] = u'0'
                try:
                    item[8] = one.xpath('div[2]/a[1]/text()')[0]
                except:
                    item[8] = u''
                flag += 1
                row = [item[i] for i in range(1, 9)]
    

    1-8分别对应之前提到的

    标题,作者,发表时间,阅读量,评论数,点赞数,打赏数,所投专题

    网页加载方式及分页问题

    我们在首页滑动鼠标会发现,信息越来越多,但是还有一点就是可以看到URL并没有发生变化,所以其他页面的信息就是异步加载了,那么接着就要去抓包了

    加载更多

    通过滑动鼠标,一段时间后我们可以看到,这个连接,但其实它已经请求了很多页面了

    page=2 page=3
    这个时候我们看到,其实有两个异步请求,已经悄悄在页面中填充了数据
    那么我们点击阅读更多又会有什么变化呢? page=4
    那么我们是不是可以通过,改变页码(page)去完成分页呢?因为首页和七日热门比较类似,按照我之前爬取七日热门的思路去抓取(spiders——简书7日热门(scrapy)),但是显然精简过得URL不能抓取首页的信息,那么没办法就只能把全部的参数都怼进去试试了,首先我们来看一下除了page这个参数之外,seen_snote_ids[]参数应该在那找 第一页

    我们看到第一页并没有带参数, 我们再去看一下第二页的请求信息

    第二页请求信息

    有很多id,那么我们应该去哪找呢,我们先去看一下第一页的源码

    第一页源码信息

    看到这些数字,是不是和第二页的参数有关系呢,经过对比确实和第二页的参数id一致,有了头绪我们再去看一下第三页的(进一步确定携带的参数)

    第三页参数

    经过分析,我们很巧的发现第三页的参数是40个第二页是20个,第一个0个,并且,第二页的id参数,我们可以在第一页源码中拿到,那第三页的是不是也可以在第二页中看到呢?,我们去看一下第二页源码

    可能存在id

    因为网页就是直接加载的,我们大概确定一下第二页的位置,然后对比去对比第三页的部分参数信息

    第三页部分参数
    大家如果仔细去对比是可以发现,确实第三页的参数包含了第一个页面和第二个页面中的id信息。
    现在差不多我们对这个网页的加载方式,以及分页方式有了进一步的理解,就是之后的每一页除了page参数改变之外,携带的seen_snote_ids[]是上(几)页的所有id参数,那么这个到底有多少页呢,我真的去不断点击加载最终,page参数停留在了15页(seen_snote_ids[]的数量看更是非常大),并且也没有出现阅读更多字样,我们来看一下 第十五页
    我们可以看到请求的URL的长度,参数一直在增加,所以我暂且就认为i这个是15页,下边给一下获取id以及分页URL的构造示例代码:
    1.获取id
            html = requests.get(url,headers = self.headers,cookies = self.cookies).text
            response = etree.HTML(html)
            ids = response.xpath('//*[@id="list-container"]/ul/li')
            for one in ids:
                one = 'seen_snote_ids[]=' + one.xpath('@data-note-id')[0]
    

    2.构造页码

        def totalPage(self):
            for i in range(1,16):
                data = '&'.join(self.params)
                url = 'http://www.jianshu.com/?' + data + '&page={}'.format(i)
                self.getData(url)
    

    遇到的问题+样例源码

    1.遇到的问题
    之前按照我简书七日热门的思路去写,最后获取到的都是重复数据,并且在添加id之后也是重复数据,罗罗攀 给我看了向右奔跑老大之前关于首页分析的文章,看了之后和我的对比,感觉差不多,但是我就是出不来数据,之后各位老哥们就说可能是参数不够吧,LEONYao老哥还说可以把参数都怼进去,满状态轰炸,向右奔跑老大之后说带个cookies可行,测试之后真的可行(一个小小的cookies困扰了很长时间,没想起来带cookies)
    2.示例代码

    # -*- coding:utf-8 -*-
    
    from lxml import etree
    import requests
    import re
    from Class.store_csv import CSV
    
    class Spider(object):
    
        headers = {
            "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36"
        }
        cookies = {
            'UM_distinctid': '15ac11bdff316-0ce09a4511f531-67f1a39-100200-15ac11bdff447d',
            'CNZZDATA1258679142': '1034687255-1492307094-%7C1493259066',
            'remember_user_token': 'W1s1MjA4MDY0XSwiJDJhJDEwJFVWVjUwbXBsS1hldkc1d0l3UG5DSmUiLCIxNDk0ODkyNTg0LjczNDM2ODgiXQ%3D%3D--f04b34c274980b45e5f7ee17c2686aeb4b567197',
            '_gat': '1',
            '_session_id': 'N0tvclN3V09wZ25UNFloZ0NrRTBVT3ZYQUR5VkRlV1c2Tno1bnNZc3dmQm9kQ3hmOGY4a0dFUlVLMDdPYWZJdCsydGJMaENZVU1XSHdZMHozblNhUERqaldYTHNWYXVPd2tISHVCeWJtbUFwMjJxQ3lyU2NZaTNoVUZsblV4Si94N2hRRC94MkJkUjhGNkNCYm1zVmM0R0ZqR2hFSFltZnhEcXVLbG54SlNSQU5lR0dtZ2MxOWlyYWVBMVl1a1lMVkFTYS8yQVF3bGFiR2hMblcweTU5cnR5ZTluTGlZdnFKbUdFWUYzcm9sZFZLOGduWFdnUU9yN3I0OTNZbWMxQ2UvbU5aQnByQmVoMFNjR1NmaDJJSXF6WHBYQXpPQnBVRVJnaVZVQ2xUR1p4MXNUaDhQSE80N1paLzg0amlBdjRxMU15a0JORlB1YXJ4V2g0b3hYZXpjR1NkSHVVdnA2RkgvVkJmdkJzdTg5ODhnUVRCSnN2cnlwRVJvWWc4N0lZMWhCMWNSMktMMWNERktycE0wcHFhTnYyK3ZoSWFSUFQzbkVyMDlXd2d5bz0tLThrdXQ2cFdRTTNaYXFRZm5RNWtYZUE9PQ%3D%3D--bc52e90a4f1d720f4766a5894866b3764c0482dd',
            '_ga': 'GA1.2.1781682389.1492310343',
            '_gid': 'GA1.2.163793537.1495583991',
            'Hm_lvt_0c0e9d9b1e7d617b3e6842e85b9fb068': '1495360310,1495416048,1495516194,1495583956',
            'Hm_lpvt_0c0e9d9b1e7d617b3e6842e85b9fb068': '1495583991'
        }
        params = []
        def __init__(self):
            field = ['标题', '作者', '发表时间', '阅读量', '评论数', '点赞数', '打赏数', '所投专题']
            self.write = CSV('main.csv', field)
        def totalPage(self):
            for i in range(1,16):
                data = '&'.join(self.params)
                url = 'http://www.jianshu.com/?' + data + '&page={}'.format(i)
                self.getData(url)
        def getData(self,url):
            print url
            html = requests.get(url,headers = self.headers,cookies = self.cookies).text
            response = etree.HTML(html)
            ids = response.xpath('//*[@id="list-container"]/ul/li')
            for one in ids:
                one = 'seen_snote_ids[]=' + one.xpath('@data-note-id')[0]
                self.params.append(one)
            item = {}
            flag = 0
            read = re.findall(r'ic-list-read"></i> (\d+)', html)
            comment = re.findall(r'ic-list-comments"></i> (\d+)', html)
            result = response.xpath('//*[@id="list-container"]/ul/li/div')
            for one in result:
                item[1] = one.xpath('a/text()')[0]
                item[2] = one.xpath('div[1]/div/a/text()')[0]
                item[3] = one.xpath('div[1]/div/span/@data-shared-at')[0]
                item[4] = read[flag]
                try:
                    item[5] = comment[flag]
                except:
                    item[5] = u''
                item[6] = one.xpath('div[2]/span/text()')[0].strip()
                try:
                    item[7] = one.xpath('div[2]/span[2]/text()')[0].strip()
                except:
                    item[7] = u'0'
                try:
                    item[8] = one.xpath('div[2]/a[1]/text()')[0]
                except:
                    item[8] = u''
                flag += 1
                row = [item[i] for i in range(1, 9)]
                self.write.writeRow(row)
    
    if __name__ == "__main__":
        jian = Spider()
        jian.totalPage()
    

    结果截图

    信息详情

    总结

    现在想来,在爬取网站时,我们可以携带尽可能全的参数(俗话说,礼多人不怪),避免遇到我这个错误,scrapy版本正在写,有兴趣的可以私聊参考源码。

    相关文章

      网友评论

      • ZemelZhu:cookies = {
        "default_font": "font2",
        "signin_redirect":"https%3A%2F%2Fwww.jianshu.com%2F",
        "Hm_lpvt_0c0e9d9b1e7d617b3e6842e85b9fb068": "1526213319",
        "locale": "zh-CN",
        "Hm_lvt_0c0e9d9b1e7d617b3e6842e85b9fb068": "1526210535,1526210625,1526210657,1526210659sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%2216353204c2859c-019071aa1763e1-b353461-2073600-16353204c292e0%22%2C%22%24device_id%22%3A%2216353204c2859c-019071aa1763e1-b353461-2073600-16353204c292e0%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_referrer%22%3A%22%22%2C%22%24latest_referrer_host%22%3A%22%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%7D%7D",
        " read_mode": "day",
        "_m7e_session": "d6c9b96bc7432cacc7430c21ba766cb3"
        }
        为什么携带这样的cookie不行

      本文标题:Python爬虫—简书首页数据抓取

      本文链接:https://www.haomeiwen.com/subject/ghunxxtx.html