Scrapy-如何从一个类别中提取所有博客文章?

Scrapy- How to extract all blog posts from a category?

我正在使用 scrapy 提取我博客的所有 post。问题是我不知道如何创建一个规则来读取任何给定博客类别中的所有 posts?

示例:在我的博客上,类别 "Environment setup" 有 17 个 post。所以在 scrapy 代码中,我可以按照给定的方式对其进行硬编码,但这不是一种非常实用的方法

start_urls=["https://edumine.wordpress.com/category/ide- configuration/environment-setup/","https://edumine.wordpress.com/category/ide-configuration/environment-setup/page/2/","https://edumine.wordpress.com/category/ide-configuration/environment-setup/page/3/"] 

我读过与此问题相关的类似 posts posted here on SO like 1, 2, 3, 4, 5, 6, 7,但我似乎无法找到我的答案。如您所见,唯一的区别是上面 url 中的页数。我如何在 scrapy 中编写一条规则,可以读取一个类别中的所有博客 post。还有一个小问题,我如何配置蜘蛛来抓取我的博客,这样当我 post 一个新的博客 post 条目时,抓取器可以立即检测到它并将其写入文件。

这就是我目前对蜘蛛的了解 class

from BlogScraper.items import BlogscraperItem
from scrapy.spiders import CrawlSpider,Rule
from scrapy.selector import Selector
from scrapy.linkextractors import LinkExtractor
from scrapy.http import Request


class MySpider(CrawlSpider):
    name = "nextpage" # give your spider a unique name because it will be used for crawling the webpages

    #allowed domain restricts the spider crawling
    allowed_domains=["https://edumine.wordpress.com/"]
    # in start_urls you have to specify the urls to crawl from
    start_urls=["https://edumine.wordpress.com/category/ide-configuration/environment-setup/"]

    '''
    start_urls=["https://edumine.wordpress.com/category/ide-configuration/environment-setup/",
                "https://edumine.wordpress.com/category/ide-configuration/environment-setup/page/2/",
                "https://edumine.wordpress.com/category/ide-configuration/environment-setup/page/3/"]


    rules = [
                Rule(SgmlLinkExtractor
                    (allow=("https://edumine.wordpress.com/category/ide-configuration/environment-setup/\d"),unique=False,follow=True))
            ]
'''
    rules= Rule(LinkExtractor(allow='https://edumine.wordpress.com/category/ide-configuration/environment-setup/page/'),follow=True,callback='parse_page')

    def parse_page(self, response):

        hxs=Selector(response)
        titles = hxs.xpath("//h1[@class='entry-title']")
        items = []
        with open("itemLog.csv","w") as f:
             for title in titles:
                item = BlogscraperItem()
                item["post_title"] = title.xpath("//h1[@class='entry-title']//text()").extract()
                item["post_time"] = title.xpath("//time[@class='entry-date']//text()").extract()
                item["text"]=title.xpath("//p//text()").extract()
                item["link"] = title.select("a/@href").extract()

                items.append(item)

                f.write('post title: {0}\n, post_time: {1}\n, post_text: {2}\n'.format(item['post_title'], item['post_time'],item['text']))
                print "#### \tTotal number of posts= ",len(items), " in category####"


        f.close()

有什么解决办法或建议吗?

您有一些可以在代码中改进的地方和两个您想要解决的问题:阅读 posts,自动抓取。

如果你想获取新博客的内容post你必须重新运行你的蜘蛛。否则你将陷入无限循环。当然,在这种情况下,你必须确保你没有抓取已经抓取的条目(数据库,在蜘蛛启动时读取可用文件等)。但是您不能拥有一个 运行 永远等待新条目的蜘蛛。这不是目的。

您将 post 存储到文件中的方法是错误的。这意味着为什么要抓取项目列表然后对它们不做任何事情?为什么要保存 parse_page 函数中的项目?为此,有 item pipelines,您应该写一个并在那里进行导出。并且 f.close() 不是必需的,因为您使用 with 语句最后为您执行此操作。

您的 rules 变量应该抛出错误,因为它不可迭代。我想知道你是否测试过你的代码。而且规则太复杂了。您可以将其简化为:

rules = [Rule(LinkExtractor(allow='page/*'), follow=True, callback='parse_page'),]

它跟在每个 URL 后面,其中包含 /page

如果您启动抓取工具,您会看到结果因您允许的域而被过滤:

Filtered offsite request to 'edumine.wordpress.com': <GET https://edumine.wordpress.com/category/ide-configuration/environment-setup/page/2/>

要解决此问题,请将您的域更改为:

allowed_domains = ["edumine.wordpress.com"]

如果你想获取其他wordpress站点,只需将其更改为

allowed_domains = ["wordpress.com"]