Scrapy爬取P2P新闻入门教程


本博客不介绍具体细节,详细入门教程可以看最下方的参考链接,本博客只介绍如何实现一个简单的能够利用百度搜索抓取和P2P相关新闻的爬虫。

安装Scrapy

pip install scrapyconda install scrapy

建立Scrapy项目

命令行中输入scrapy startproject p2p建立一个名为"p2p"的scrapy项目,其目录结构如下:

p2p/
    scrapy.cfg
    p2p/
        __init__.py
        items.py
        pipelines.py
        settings.py
        spiders/
            __init__.py
            ...

其中items.py用来定义数据结构,pipelines.py用于对items进行处理并储存,本项目不使用pipline,spiders里面是我们的爬虫代码,用于抓取数据。

修改配置文件

为了抓取百度新闻的内容,我们需要修改settings.py配置文件,以下部分需要修改:

  • ROBOTSTXT_OBEY = False,这是为了让爬虫不遵守robotstxt协议,默认百度是不让抓取的
  • USER_AGENT = 'Mozilla/5.0',改成和你浏览器相对应的值,我的是Firefox浏览器,不然response会返回"favicon.ico"
  • FEED_EXPORT_ENCODING = 'utf-8',防止使用Unicode编码,难以显示

定义Item

items.py里的item类用于保存数据,例如:

import scrapy

class P2PItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    url = scrapy.Field()
    title = scrapy.Field()
    domain = scrapy.Field()
    content = scrapy.Field()

我们保存新闻的url、标题、网站域名和内容

编写Spider类

spiders目录下创建p2p_spider.py文件

import scrapy
import os
from p2p.items import P2PItem
import re
import logging

class P2PSpider(scrapy.Spider):
    item_max = 20 #设一个抓取文章的上限,防止一直抓取
    url_max = 1000 #设一个访问url的上限

    item_num = 0
    url_num = 0
    
    name = "p2p"
    allowed_domains = ["sohu.com","ifeng.com","news.baidu.com"] #将一些主要新闻网站加入抓取范围,当然baidu也得加入其中,因为翻页后还在baidu域名下面
    start_urls = [
        "https://news.baidu.com/ns?word=p2p"   #在百度新闻搜索中搜“p2p”
    ]

    def parse(self, response):
        logging.info(f'enter baidu : {response.url}')
        url_res = response.css("div.result h3.c-title a::attr(href)").extract()  #提取新闻的url

        url_page = response.css("p#page a::attr(href)").extract() #提取翻页的url

        for u in url_res:
            self.url_num += 1
            
            if (self.url_num < self.url_max) and (self.item_num < self.item_max):
                logging.debug(f'url id {self.url_num}/{self.url_max} : {u}')
                if "sohu.com" in u:
                    yield scrapy.Request(u,callback=self.parse_sohu) #由于不同站点的html格式不一样,所以callback调用不同函数分别处理
                elif "ifeng.com" in u:
                    yield scrapy.Request(u,callback=self.parse_ifeng)
            


        for u in url_page:
            u = response.urljoin(u)
            self.url_num += 1
            
            if (self.url_num < self.url_max) and (self.item_num < self.item_max):
                logging.debug(f'url id {self.url_num}/{self.url_max} : {u}')
                if "news.baidu.com" in u:
                    yield scrapy.Request(u,callback=self.parse)
            

    def parse_sohu(self,response):
        logging.info(f'parse sohu {self.item_num}/{self.item_max}: {response.url}')
        
        title = response.css("div.text-title h1::text").extract_first()
        content = ''.join(response.xpath("//article//text()").extract())
        
        if (title is not None) and (content is not None):
            item = P2PItem()
            item['url'] = response.url
            item['title'] = title.replace(' ','')
            item['domain'] = 'sohu.com'
            item['content'] = re.sub(r'\s+',r'\n',content.replace(' ',''))
            
            self.item_num+=1
            if self.item_num<self.item_max:
                return item #返回数据结构
            


    def parse_ifeng(self,response):
        logging.info(f'parse ifeng {self.item_num}/{self.item_max}: {response.url}')

        title = response.css("h1#artical_topic::text").extract_first()
        content = ''.join(response.xpath("//div[@id='main_content']//text()").extract())

        if (title is not None) and (content is not None):
            item = P2PItem()
            item['url'] = response.url

            item['title'] = title.replace(' ','')
            item['domain'] = 'ifeng.com'
            item['content'] = re.sub(r'\s+',r'\n',content.replace(' ',''))
            
            self.item_num+=1
            if self.item_num<self.item_max:
                return item
      

运行爬虫

进入包含scrapy.cfg文件的目录,执行下面命令运行爬虫,其中“p2p”是爬虫的名字,在settings.pyBOT_NAME = 'p2p'设置,默认为工程名。并将结果保存成csv格式。

scrapy crawl p2p -o data/items.csv -L INFO

-L INFO是只显示INFO以上级别的信息,不然会有大量DEBUG信息输出。

结果如下
crawl_csv
我们程序中设的是抓20篇新闻,实际只抓到了15篇,这是由于我们只抓搜狐和凤凰的新闻,而凤凰网只有财经板块能抓到,其他板块HTML格式不一样,需要单独配置。


参考链接

源代码
Scrapy官方教程
网友整理的系列教程
解决favicon.io问题

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值