scrapy爬取CSDN论坛问题及内容

爬虫相信大家都有所了解,我对爬虫就不做详细介绍了。本次我决定使用scrapy爬取CSDN论坛发布的问题以及回答的内容。

首先,我们需要创建一个scrapy项目。

scrapy startproject test1

然后进入scrapy项目中,创建一个爬虫。

#进入scrapy项目中
cd test1

#创建爬虫
scrapy genspider csdn_spider  bbs.csdn.net

创建爬虫时,前两个参数是固定的,第三个参数是你要创建的爬虫文件的名字,第四个参数是你要爬取的网站的网址,此处我们先随便写上一个。四个参数缺一不可。

接下来我们打开我们的项目,找到spider文件夹中我们刚创建的 'csdn_spider.py'文件。下面我们就要开始我们的爬虫项目了。

先对CSDN论坛进行分析,我们发现论坛的分页是比较简单的,每一页的网址只有特定地方的数字变了一下。所以我们可以创建一个函数对论坛每一页的url进行拼接。

#拼接url
def joint_url(url):
    # for i in range(1,101):
    #此处范围可以先改小点进行测试,测试成功后可以再进行增大范围的操作。
    return [url.format(i) for i in range(1,10)]

下面分析每一个问题的url。我们会发现每个问题的url是这样的。

<a href="/topics/392451197" class="topic_title" target="_blank" title="关于读取EXCEL出现乱码的问题">关于读取EXCEL出现乱码的问题</a>

这个超链接是不完整的,所以我们需要再写一个函数拼接问题的url。

#拼接各个问题的url
def question_url(url):
    #筛选出符合条件的url(只有满足条件的才是问题的url)
    if '/topics' in url:
        return "https://bbs.csdn.net"+url
    else:
        return None

网址都得到了,那么下面就可以爬取网页,并分析网页中我们想要得到的内容了。

下面就开始爬虫的整个流程。

首先,确定要爬取的种子网页。

因为我们设定了url拼接,所以我们的种子网页是多个,这里展示一下。

#导入类库
import scrapy
from scrapy import Request


class CsdnspiderSpider(scrapy.Spider):
    #爬虫名字,用来启动爬虫
    name = 'csdn_spider'
    #过滤掉不满足条件的网址
    allowed_domains = ['bbs.csdn.net']

    def __init__(self):
        #种子网址,与上面定义的拼接函数搭配使用。
        self.urls = 'https://bbs.csdn.net/forums/OL_Script?page={}'

    此处函数名必须是start_requests
    def start_requests(self):
        #循环访问每一页
        for url_str in joint_url(self.urls):
            #迭代器,参数1:访问网站url,参数2:回调函数,函数名必须是parse    
            yield Request(url=url_str,callback=self.parse)

获得返回的网页内容后,对内容进行筛选

    #此处函数名必须是parse
    def parse(self, response):
        """
        提取每一页中的问题
        :param response:
        :return:
        """
        #使用xpath,匹配出问题的链接
        all_title_urls = response.xpath('//td[@class="forums_topic"]/a/@href').extract()

        for one_title in all_title_urls:
            #完整的每个问题的url
            full_url = question_url(one_title)
            if full_url:
                #下面的回调函数函数名可以是其他的,只有第一个回调函数名必须是parse。
                yield Request(url=full_url,callback=self.question)

此时,我们需要找到 'item.py'文件,它的作用就跟Django中 'models.py' 相同。然后在里面输入以下代码。


class CsdnspiderItem(scrapy.Item):
    title = scrapy.Field()
    content = scrapy.Field()

接下来回到 'csdn_spider.py' 文件中,首先在最上方需要导入刚才创建的类。

from test1.items import CsdnspiderItem

再对每一个问题网址里面的内容进行筛选。

 def question(self,response):
        """
        提取每个问题中的回答内容
        :param response:
        :return:
        """
        # print(response.body)
        try:
            one_question_title = response.xpath('//span[@class="title text_overflow"]/text()').extract()
            one_question_title = one_question_title[0]
        except:
            one_question_title = 'none'
        try:
            one_question_contents = response.xpath('//div[@class="post_body post_body_min_h"]/text()').extract()
        except:
            one_question_contents = 'none'
        contents_str = ''
        for i in one_question_contents:
            contents_str += i

        contents_str = ' '.join(contents_str.split())
        item = CsdnspiderItem()
        item["title"] = one_question_title
        item["content"] = contents_str
        yield item

数据现在已经有了,那么我们把数据存到哪里呢?不要着急,scrapy已经为我们考虑到了。打开 'piplines.py' 文件,在这里,我们将进行我们的数据库存储操作。这里我们使用sqlite数据库。

import sqlite3

class CsdnspiderPipeline(object):
    def __init__(self):
        self.conn = sqlite3.connect('./../csdn.db')
        self.cur = self.conn.cursor()
         self.cur.execute(
            "create table IF NOT EXISTS infos(id integer primary key autoincrement, question text,answer text);")
        self.conn.commit()

    def process_item(self, item, spider):
        self.cur.execute('insert into infos(question,answer) values(?,?)',[item['title'],item['content']])
        self.conn.commit()
        return item

注意,我们还需要去'setting.py'文件中设置一下才可以使用。

ITEM_PIPELINES = {
   'test1.pipelines.CsdnspiderPipeline': 300,
}

下面,我们在终端中输入 ‘scrapy crawl csdn_spider’就可以运行爬虫了。

有的时候,这样容易被封掉,我们可以使用浏览器模拟的操作,找到 ‘middlewares.py’ 文件,这时scrapy的中间件,我们在这里写浏览器模拟的类。

from scrapy.http import HtmlResponse
from selenium.common.exceptions import TimeoutException
import time
from selenium import webdriver
from selenium.webdriver.firefox.options import Options as FOptions

class SeleniumMiddleware(object):
    def __init__(self):
        self.options = FOptions()
        self.options.add_argument('-headless')  # 无头模式
        self.browser = webdriver.Firefox(executable_path='E:\FireFox\geckodriver\geckodriver.exe',
                                         firefox_options=self.options)

    def process_request(self,request,spider):
        try:
            print("url is ::::::",request.url)
            self.browser.get(request.url)
        except TimeoutException as e:
            print("超时")
        time.sleep(2)
        return HtmlResponse(url=self.browser.current_url,body=self.browser.page_source,
                            encoding="utf-8",request=request)

然后再 'setting.py' 中设置

DOWNLOADER_MIDDLEWARES = {
   'test1.middlewares.SeleniumMiddleware': 543,
}

浏览器模拟需要用到的东西,在我的浏览器模拟的那个博客中有讲到,这里就不过多讲了。

现在算是一个比较完整的爬虫项目了。总的来说,比较简单,适合初学者入门学习。

猜你喜欢

转载自blog.csdn.net/j123__/article/details/82822039