Scrapy项目基本流程--以中银保报为例

以' 中国银行保险报' 资讯爬取MongoDB入库 为例, 不讲原理, 只为程序化的工作服务.scrapy每次根据不同的网站只需更改少量地方就可实现信息抓取


WX20220104-123157.png

一, 准备阶段

1, 建立项目目录

终端 (terminal) 输入:scrapy startproject general_spider(name随意)


WX20220104-115934@2x.png

2, 进入项目, 看名字大概知道每个文件的含义:

WX20220104-120328.png

右键将项目作为根目录:


WX20220104-120448.png

3, 修改配置文件settings,

#开始改的不多, 这些本地调试足够了, 后期功能增加再改来得及:
ROBOTSTXT_OBEY = False

ITEM_PIPELINES = {
    'general_spider.pipelines.PipelineDB': 300,
}
MONGO_URL='xxxxxx'
DOWNLOADER_MIDDLEWARES = {
    'general_spider.middlewares.MyUserAgentMiddleware': 600,
    'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None,
    'general_spider.middlewares.ProxyMiddleware': 350,# 没有代理可以注释
    'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 400,# 没有代理可以注释
}
# 日志
LOG_LEVEL = 'WARNING'#DEBUG ,INFO ,ERROR ,CRITICAL ,
LOG_FILE = './log.log'

#UA 网上一大堆, 复制过来就行
USER_AGENT = [
    'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Mobile Safari/537.36',
    'Mozilla/5.0 (iPhone; CPU iPhone OS 10_2 like Mac OS X) AppleWebKit/602.3.12 (KHTML, like Gecko) Mobile/14C92 MicroMessenger/6.5.16 NetType/WIFI Language/zh_CN',
    'Mozilla/5.0 (Linux; U; Android 5.1.1; zh-cn; MI 4S Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.146 Mobile Safari/537.36 XiaoMi/MiuiBrowser/9.1.3',
    'Mozilla/5.0 (iPhone; CPU iPhone OS 10_2 like Mac OS X) AppleWebKit/602.3.12 (KHTML, like Gecko) Mobile/14C92 MicroMessenger/6.5.16 NetType/WIFI Language/zh_CN',
    'Mozilla/5.0 (Linux; U; Android 5.1.1; zh-cn; MI 4S Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.146 Mobile Safari/537.36 XiaoMi/MiuiBrowser/9.1.3',
    'Mozilla/5.0 (Linux; U; Android 7.0; zh-CN; SM-G9550 Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/40.0.2214.89 UCBrowser/11.7.0.953 Mobile Safari/537.36',
    'Mozilla/5.0 (Linux; U; Android 6.0.1; zh-CN; SM-C7000 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/40.0.2214.89 UCBrowser/11.6.2.948 Mobile Safari/537.36',
    ]

4,修改中间件middlewares.py

# 保留这个换UA 的class, IP
class MyUserAgentMiddleware(UserAgentMiddleware):
    '''
    设置User-Agent
    '''

    def __init__(self, user_agent):
        self.user_agent = user_agent

    @classmethod
    def from_crawler(cls, crawler):
        return cls(
            user_agent=crawler.settings.get('USER_AGENT')
        )

    def process_request(self, request, spider):
        agent = random.choice(self.user_agent)
        request.headers['User-Agent'] = agent

class ProxyMiddleware():
    ''' 换ip, 这里以阿布云为例'''
    def __init__(self, settings):
        self.logger = logging.getLogger(__name__)
        self.settings = settings
        self.proxy_type = self.settings.get('GET_PROXY_TYPE', 'no')
        self.last_fetch_proxy_time = time.time()

    @classmethod
    def from_crawler(cls, crawler):
        return cls(crawler.settings)

    def process_request(self, request, spider):
        # 设置headers Connection: close
        request.headers['Connection'] = 'close'
        
        proxyServer, proxyAuth = get_abuyun_pro()
        request.meta["proxy"] = proxyServer
        request.headers["Proxy-Authorization"] = proxyAuth
        request.headers["Proxy-Switch-Ip"] = 'yes'
        

5, 修改pipeline.py, 增加入库功能(这里以MongoDB为例):

from pymongo import MongoClient

from general_spider import settings
class PipelineDB(object):

    def __init__(self, logger, client):
        self.logger = logger
        self.client = client
        self.collection = self.client['pa_crawler']

    @classmethod
    def from_crawler(cls, crawler):
        return cls(
            logger=crawler.spider.logger,
            client=MongoClient(settings.MONGO_URL, maxPoolSize=10)
        )

    def process_item(self, item, spider):
        table_name = 'xxxx' #表明字

        # 如果文章存在, 不存该条
        if self.collection[table_name].find({'article_title': item["article_title"]}).count() == 0:
            # 这里存的是格式化好 的数据
            self.collection[table_name].insert(item)
            self.logger.info(f'{table_name}-{item["article_title"]},提交数据到 mongo 成功')
            return item
        else:
            self.logger.info(f'{table_name}-{item["article_title"]},mongo数据库已经存在, 舍弃')
            return item

    def close_spider(self, spider):
        self.client.close()

6, 修改items.py, 入库的字段


import scrapy


class BadouItem(scrapy.Item):
    # define the fields for your item here like:
    article_title = scrapy.Field()#标题
    article_content_html = scrapy.Field()#原始内容
    article_content_raw = scrapy.Field()#纯文字内容,去除html标签
    article_content = scrapy.Field()#纯文字内容+图片url(插在文章里)
    article_cover = scrapy.Field()#封面
    crawl_date = scrapy.Field()#抓取时间
    ref_url = scrapy.Field()#文章url
    publish_time = scrapy.Field()#发布时间
    site = scrapy.Field()#平台
    pictures = scrapy.Field()#文章原始图片
    _id = scrapy.Field()#文章原始图片

二, 编写爬虫代码

在spiders里建一个.py文件


WX20220104-122907.png

class Baoxianbao(scrapy.Spider):
    '''
    中国银行保险报  资讯
    '''
    name='baoxianbao'# spider的名字, 
    start_urls=['http://www.cbimc.cn/']# 域名

    def start_requests(self):

        self.headers = {
            'Connection': 'keep-alive',
            'Upgrade-Insecure-Requests': '1',
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
            'Referer': 'http://www.cbimc.cn/node_7037.html',
            'Accept-Language': 'zh-CN,zh;q=0.9',
        }
        for category in ['07','08',10,12,16,18,29,32,33,34,35,36,37,38,39]:#每个分类
            url=f'http://www.cbimc.cn/node_70{category}.html'
            #post -->scrapy.FormRequest(...)
            yield scrapy.Request(url, headers=self.headers, callback=self.parse)

    def parse(self,response):
        # 文章链接, 标题, 封面, 发布时间
        urls=response.xpath('//div[@class="list nav_left_a1"]//li[@class="list_item"]/a/@href').extract()
        titles=response.xpath('//div[@class="list nav_left_a1"]//li[@class="list_item"]//h1/text()').extract()
        article_covers=response.xpath('//div[@class="list nav_left_a1"]//li[@class="list_item"]//img/@src').extract()
        publish_times=response.xpath('//div[@class="list nav_left_a1"]//li[@class="list_item"]//span/text()').extract()

        for url,title,article_cover,publish_time in zip(urls,titles,article_covers,publish_times):
            item=BadouItem()

            item['publish_time']=publish_time
            item['article_cover']=article_cover
            item['article_title']=title
            item['ref_url'] =url
            item['crawl_date'] = str(datetime.datetime.now()).split('.')[0]  # 抓取时间
            _id=url.split('_')[-1].split('.')[0]
            # meta为传递的变量, json格式
            yield scrapy.Request(url, headers=self.headers, callback=self.parse_content,meta=item)

    def parse_content(self,response):
        item=response.meta
        text=response.text
        content=scrapy.Selector(text=text).css('.detail-d').extract_first()
        item['article_content_html'] = content# 原始内容
        article_content_raw,pictures,article_content=parse_content(content)
        item['article_content_raw']=article_content_raw#纯文字内容,去除html标签
        item['article_content']=article_content#纯文字内容+图片url(插在文章里)

        item['site']='中国银行保险报'
        item['pictures']=pictures#图片

        yield item

三, 编写run.py

WX20220104-133554.png
# 第一种运行方法
from scrapy.cmdline import execute

execute(['scrapy', 'crawl', 'baoxianbao'])
# execute(['scrapy', 'crawl', '第二个爬虫名字'])# 多个爬虫复制一行就OK

# 第二种运行方法
from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings

process = CrawlerProcess(get_project_settings())
process.crawl('baoxianbao')
#process.crawl('第二个爬虫名字')# 多个爬虫复制一行就OK

process.start()

run起来, 结果刚好抓了100条(剔除了几个老新闻):


WX20220104-133936@2x.png

看看MongoDB里badou这张表:


WX20220104-134259@2x.png

附: 有一个文章解析方法parse_content(), 目的是HTML提取纯文本和图片:


def parse_content(content):
    '''去除HTML标签, 保留文字, 图片'''
    html_ = etree.HTML(content)
    # 纯文字
    article_content_raw = re.sub('<.*?>', '', content).replace('&nbsp;', '\n')  # html_.xpath('string(.)')
    # 图片
    pictures_html = re.findall('<img.*?>', content)
    pictures = []
    # 图文
    for pic_html in pictures_html:
        pic = re.findall(r'img.*?(http.*?)\"', pic_html)[0]
        pictures.append(pic)
        content = content.replace(pic_html, pic)
    # content=etree.HTML(content)
    article_content = re.sub('<.*?>', '', content).replace('&nbsp;', '')
    return article_content_raw, pictures, article_content
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,186评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,858评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,620评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,888评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,009评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,149评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,204评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,956评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,385评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,698评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,863评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,544评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,185评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,899评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,141评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,684评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,750评论 2 351