美文网首页
Scrapy-IT之家评论爬虫

Scrapy-IT之家评论爬虫

作者: AmazingUU | 来源:发表于2018-10-14 19:24 被阅读0次

    引言

    最近在学习Python爬虫,这里推荐一个入门爬虫的博客系列
    https://github.com/Ehco1996/Python-crawler
    博主写的对新手很友好,很适合入门。

    我写这篇文章的目的是记录一下在学习他的
    从零开始写Python爬虫 --- 爬虫应用:IT之家热门段子(评论)爬取
    中做的改进和遇到的问题。

    思路

    和原文爬取特定分类新闻下的热评不同的是,我是爬取IT之家首页的最热排行里24小时阅读榜中文章的热门评论,增加一下热评的时效性。

    根据原文,我的思路如下:

    1. 获取首页最热排行里文章的url
    2. 根据对应url获取newsID,再将newsID和type数据post给接口http://it.ithome.com/ithome/getajaxdata.aspx获取返回的热评数据
    3. 解析出热评的标题、评论人、时间、内容、支持数和反对数,进行存储

    本以为能够很顺利的实现,结果还是遇到了一些问题。

    问题

    原文是用requests和多进程实现爬取速度的提升,由于Scrapy本身就是利用多进程实现爬取速度的提升,再加上我想换一种方法实现,这里就采用Scrapy实现。下面就是遇到的问题。

    1. newsID在url中被/隔开,需要进行拼接

    原文中给出的newsID直接在url中,例:https://www.ithome.com/html/it/323076.htm ,但是最热排行里的文章的newsID在url中是被分割的,例:https://www.ithome.com/0/388/459.htm
    这个很容易解决,正则表达式匹配一下再拼接就搞定了。代码如下:

        # 选出newsID,例:https://www.ithome.com/0/388/110.htm匹配出[388,110]
        pattern = re.compile(r'(\d\d\d)')
        newsID_list = pattern.findall(link)
        newsID = newsID_list[0] + newsID_list[1]  # 拼接出newsID
    

    2. 接口post数据类型改变

    分析接口http://it.ithome.com/ithome/getajaxdata.aspx发现,目前post数据不仅仅是newsID和type,而是又加了两个字段hash和pid。

    pid好弄,直接1就行了,关键是hash怎么拿到,这个估计也是为了防止爬虫新加的字段。然后就是花了很长时间分析怎么拿到hash值。终于在漫长的网页源码中找到了hash的影子,在每篇新闻的评论的html源码中的head里的script中找到了hash。

    找到了就容易了,直接爬下来,但是发现爬下来的数据里并没有script标签,本来script应该包含在iframe标签内的,结果爬下来的数据直接<iframe ...... id="ifcomment">< /iframe>结束了,中间的html源码都没有。

    本来以为终于能拿到hash了, 结果还是不行,接着找hash。分析接口发现referer:https://dyn.ithome.com/comment/388459 ,点开这个url,正是热评的界面,分析源码发现hash值也在script标签里。

    爬这个url发现有hash值

    爬下来的数据有hash就简单了,接着就是取出script标签,正则匹配出hash,最后将newsID、hash、pid、type一起post给接口就可以拿到返回数据了。找到hash是整个项目中最关键的问题。代码如下:

        # hash在script标签内
        script = response.xpath('/html/head/script[3]/text()').extract()[0]
        # 选出hash,例:var ch11 = '0A56BCA76AE1AD61';匹配出0A56BCA76AE1AD61
        pattern = re.compile(r'\w{16}')
        hash = pattern.search(script).group()
        # print(hash)
        post_url = 'https://dyn.ithome.com/ithome/getajaxdata.aspx'  # post url
        # post数据为newsID,hash,pid,type
        yield scrapy.FormRequest(
            url=post_url,
            meta={'title': title},
            formdata={'newsID': newsID, 'hash': hash, 'pid': '1', 'type': 'hotcomment'},
            callback=get_hot_comment
        )
    

    3. 接口返回数据为json格式,不能使用xpath找到标签

    第二步post之后,返回的response本来想直接使用xpath取出各个评论数据,发现取不出来。分析发现返回的response为json格式。

    将response.text用json.loads()格式化,并取出html,最后再用BeautifulSoup()格式化一下,评论的各个数据就很容易取出来了。

    代码如下:

        # 分析response.text,发现为json格式,'html'对应html源码,即{'html':<li>...}
        html = json.loads(response.text)['html']
        # html源码格式化
        soup = BeautifulSoup(html, 'lxml')
        # 每条热评在class='entry'的li标签内
        li_list = soup.find_all('li', class_='entry')
        for li in li_list:
            # 分析html源码,取出热评对应数据
            item['username'] = li.find('span', class_='nick').text
            item['time'] = li.find('span', class_='posandtime').text.split('\xa0')[1]
            item['content'] = li.find('p').text
            like = li.find('a', class_='s').text
            hate = li.find('a', class_='a').text
            # 选出点赞数和反对数,例:支持(100)匹配出100
            item['like_num'] = re.search(r'\d+', like).group()
            item['hate_num'] = re.search(r'\d+', hate).group()
            # print(item)
            yield item
    

    4. 设置ROBOTSTXT_OBEY = False,否则scrapy自动forbidden了

    前面忘了说,需要在settings.py里将ROBOTSTXT_OBEY设为False,否则scrapy直接根据网站robot.text自动forbidden了。这里需要说一下,该爬虫项目仅供学习交流使用,爬取时降低速度,减少对端服务器压力。

    总结

    上面四个问题解决之后,整个项目就没什么大的问题了。其中最关键的还是拿到hash值。还有需要说明的一点是,当前接口post的数据为newsID、hash、pid、type,后面可能IT之家还会修改,爬取时注意post数据是否改变。

    项目地址

    https://github.com/AmazingUU/Scrapy-IT_home_hot_comment
    上面是项目地址,觉得还可以的话,给个star哦

    相关文章

      网友评论

          本文标题:Scrapy-IT之家评论爬虫

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