2015-09-28 33 views
2

我正在使用scrapy來提取我的博客的所有帖子。問題是我不知道如何創建一個讀取任何給定的博客類別中的所有帖子的規則?Scrapy-如何從一個類別中提取所有博客文章?

示例:在我的博客上,「環境設置」類別有17個帖子。所以在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/"] 

我已閱讀與此相關的問題在這裏張貼在類似的職位,像12,​​,456,7,但我似乎無法找到我的答案。正如你所看到的,唯一的區別就是上面url的頁數。我如何在scrapy中編寫一個可讀取類別中所有博客文章的規則。另一個微不足道的問題是,我如何配置蜘蛛來抓取我的博客,以便當我發佈新的博客文章條目時,爬蟲可以立即檢測到它並將其寫入文件。

這是我迄今爲止的蜘蛛類

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() 

任何幫助或建議,以解決呢?

+0

由於wordpress存儲在數據庫中的帖子,爲什麼不使用d atabase而不是scrapy? –

+0

因爲,我希望蜘蛛不僅可以抓取我的博客,還可以抓取其他博客,我認爲單靠scrapy就是最好的選擇。 – Ashish

回答

1

您可以在代碼中改進一些東西,並解決兩個您想要解決的問題:閱讀帖子,自動抓取。

如果你想獲得新的博客文章的內容,你必須重新運行你的蜘蛛。否則,你會有一個無限循環。當然,在這種情況下,您必須確保您不會刮取已經被刮取的條目(數據庫,在蜘蛛啓動時讀取可用文件等)。但是你不能有一個永遠在運行的蜘蛛並等待新的輸入。這不是目的。

將文章存儲到文件中的方法是錯誤的。這意味着你爲什麼要刮掉一系列物品,然後對它們不做任何處理?爲什麼你將這些項目保存在parse_page函數中?爲此,有item pipelines,你應該寫一個,並在那裏輸出。並且f.close()不是必需的,因爲您使用with語句最後爲您完成此操作。

你的rules變量應該拋出一個錯誤,因爲它是不可迭代的。我想知道你是否測試過你的代碼。規則太複雜。你可以把它簡化爲這樣:

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

而且也沿用其在它/page每個URL。

如果您啓動刮板,你會看到的結果,因爲你的允許域過濾:

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"] 
+0

感謝你@GHajba這樣一個精心設計的答案。感謝您指出錯誤和可能的解決方案。這是非常豐富的。我剛剛開始使用scrapy,所以架構還不清楚。任何好的參考,容易理解的項目管道將不勝感激。截至目前,官方文件對我來說有點沉重。是的規則變量是拋出一個錯誤,但我不知道如何解決它。 – Ashish

+0

另一個相關的問題是,有時如果博客文章太長,我們會看到像「繼續閱讀」這樣的url鏈接,點擊它可以發送到完整文章。我如何去編碼它在xpath中? – Ashish

+0

有幾種方法。我不會在XPath中編寫它,而是在'parse_page'中查看內容是否包含鏈接。如果是的話,我會用另一個解析詳細帖子的解析器函數「產生」一個新的「Request」給詳細的文章。在這種情況下,我不會'發現'找到的項目。這是一種方法。 – GHajba

相關問題