scrapy爬取天涯帖子内容

主要代码

import scrapy
from scrapy import Selector
from first.items import TYItem
import re

class TianyaSpider(scrapy.Spider):
    name = 'tianya'
    allowed_domains=['tianya.cn']
    # 对请求的返回进行处理的配置
    meta = {
        'dont_redirect': True,  # 禁止网页重定向
        'handle_httpstatus_list': [301, 302]  # 对哪些异常返回进行处理
    }

    cookies={}
    header={ 'User-Agent': 'Mozilla / 5.0(X11;Linux x86_64) AppleWebKit /537.36(KHTML, likeGecko) Chrome / 54.0.2840.71Safari / 537.36'}

    start_urls=[
                "http://bbs.tianya.cn/post-funinfo-7049670-1.shtml",
                "http://bbs.tianya.cn/post-16-1632189-1.shtml",
                "http://bbs.tianya.cn/post-16-1642094-1.shtml",
                ]

    def get_url(self,pre_url):
        url_head = pre_url.split('-')[0:-1]
        page = int(pre_url.split('-')[-1].split('.')[0])+1
        return '-'.join(url_head)+'-'+str(page)+'.shtml'


    def start_requests(self):
        for url in self.start_urls:
            yield scrapy.Request(url=url,callback=self.parse,headers=self.header,meta=self.meta)

    reg = re.compile(r'时间:(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})')

    def parse(self, response):
        if response.status != 200:
            return
        item = TYItem()
        item['title'] = Selector(response).xpath('//*[@id="post_head"]/h1/span[1]/span/text()').extract()[0]
        content_div = Selector(response).xpath('//div[@class="atl-main"]/div[starts-with(@class,"atl-item")]')

        for each in content_div:
            try:
                item['author'] = each.xpath('.//div[@class="atl-info"]/span/a/text()').extract()[0]
            except:
                item['author'] = ""
            item['content'] = each.xpath('.//div[starts-with(@class,"bbs-content")]').xpath('string(.)').extract()[
                0]. \
                replace('\r\n', '').replace('\t', '').replace('\u3000', '').replace('\n', "")
            try:
                post_time = each.xpath('.//div[@class="atl-info"]/span[2]/text()').extract()[0]
                item['post_time'] = re.findall(self.reg, post_time)[0]
            except IndexError:
                item['post_time'] = ""

            try:
                item['floor'] = each.xpath(
                    './/div[starts-with(@class,"bbs-content")]/following-sibling::div[1]/span/text()').extract()[0][
                                0:-1]
            except IndexError:
                item['floor'] = ''
            yield item

        next_url = self.get_url(response.url)
        yield scrapy.Request(url=next_url, callback=self.parse, headers=self.header,
                             cookies=self.cookies, meta=self.meta)

items.py

class TYItem(scrapy.Item):
    title=scrapy.Field()#帖子标题
    author = scrapy.Field()#楼主和层主
    content=scrapy.Field()#内容,层中层的内容没有爬取
    post_time=scrapy.Field()#发表时间
    floor=scrapy.Field()#楼数

在爬取帖子内容content的时候,会出现比较奇怪的字符\u3000,或者\xa0等等,可以用replace替换成空格
天涯帖子的格式还是比较规范的,xpath选择起来不是太费事(特此一体,某数字论坛,年代久远,帖子内容首页,前2页,最后几页样式不一样,坑!)
分析天涯帖子的网址,比如
http://bbs.tianya.cn/post-funinfo-7049670-1.shtml
其中7049670可以认为是文章的id,1是页数,值得一提的是,天涯在处理超过页数的请求时,会返回301,
Status Code:301 Moved Permanently重定向到最后一页,我们可以根据response.status判断是否帖子已经结束
至于为什么在parse函数里面有try…exception…因为帖子的第一个content,就是楼主的主帖html样式和回复贴不太一样,根据同样的xpath选取不到,会跑出IndexError,没什么好的解决办法,只能这么的简单粗暴,捕获异样,把内容设置为空字符串
pipelines.py

import pymongo
from datetime import datetime
import threading
client=pymongo.MongoClient(host='127.0.0.1',port=27017)
db=client['scrapy_data']['tianya']

class TYPipeline(object):

    def process_item(self,item ,spider):
        with open('tianya4.txt','a') as f:
            f.write(str(item))
            f.write('\n')

            # if item['post_time'] !='':
            #     item['post_time']=datetime.strptime(item['post_time'],'%Y-%m-%d %H:%M:%S')
            # if item['floor'] !='':
            #     item['floor']=int(item['floor'])
            # self.db.insert(dict(item))
        # return item

注释掉的部分是存入mongodb的代码部分,把格式转化是为了在mongodb中便于查询.
讲道理的话可以根据上层的的网址,比如莲蓬鬼话http://bbs.tianya.cn/list-16-1.shtml
爬取到每个帖子的路径,href属性

<a href="/post-16-1632076-1.shtml" target="_blank">
亲身经历病房灵异,直接崩溃无神论者!!<span class="art-ico art-ico-3" title="内有7张图片"></span></a>

下一页的超链接“`
/list.jsp?item=16&nextid=1478769822000

用不同的parse函数处理即可,这样理论上可以爬取一个板块所有的帖子,由于天涯板块还有子版块,所以仅仅这样只能爬取某个板块.
处理帖子的parse函数可以通用,例子中start_urls三个网址属于两个不同的板块,最后爬取的文件基本是这样的(懒得截图,就这么看把)

{‘author’:” ”,
‘content’: ‘大家。…….家看看就行了。’,
‘floor’: “”,
‘post_time’: ”,
‘title’: ‘[天涯头……..’}
{‘author’: ‘小鉴定师大宝’,
‘content’: ‘@小鉴定师大宝 2016-08-21 ’
‘15:23:16大家好,我是一个DNA鉴定师……’,
‘floor’: ‘2’,
‘post_time’: ‘2016-08-21 15:24:10’,
‘title’: ‘[天涯头条]我是一……..’}
“`
感觉还有待完善

展开阅读全文

没有更多推荐了,返回首页