scrapy爬取知名技术文章网站

                                 scrapy爬取知名技术文章网站

 

一、scrapy安装以及目录结构介绍

    1、安装

        pip install -i https://pypi.douban.com/simple/ scrapy

        安装Scrapy报错:

            Could not find a version that satisfies the requirement Twisted>=13.1.0 (from Scrapy) (from versions: )
            No matching distribution found for Twisted>=13.1.0 (from Scrapy)

        原因是没有安装Twisted:

            进入https://pypi.org/project/Twisted/#files下载Twisted-19.2.1.tar.bz2

            tar -xjvf Twisted-19.2.1.tar.bz2
            cd Twisted-19.2.1
            python setup.py install

            成功 

    2、创建项目

        scrapy startproject ArticleSpider

        创建模板:

            scrapy genspider jobbole blog.jobbole.com

    3、项目目录结构

        

二、pycharm调试scrapy执行流程

    1、在目录下创建main.py文件,文件内容如下:

        

from scrapy.cmdline import execute

import sys
import os

# 获取main.py文件的父目录
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
execute(["scrapy", "crawl", "jobbole"])

    2、修改settings.py中ROBOTSTXT_OBEY = True为ROBOTSTXT_OBEY = False

    3、选中main.py文件,鼠标右键,选择"Debug main"鼠标左键点击,就可以进入debug调试模式了

        成功:

            

三、xpath用法

    1、xpath简介

        (1) xpath使用路径表达式在xml和html中进行导航;

        (2) xpath包含标准函数库;

        (3) xpath是一个w3c的标准。

    2、xpath节点关系

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

</body>
</html>

        (1) 父节点

            <head>为<title>的父节点

        (2) 子节点

            <title>为<head>的子节点

        (3) 同胞节点

            <title>和<meta>为同胞节点

        (4) 先辈节点

            <html>和<head>为<title>的父辈节点

        (5) 后代节点

            <head>和<title>为<html>的后辈节点

    3、xpath语法

表达式说明
article选取所有article元素的所有子节点
/article选取根元素article
article/a选取所有属于article的子元素的a元素
//div选取所有div子元素(不论出现在文档任何地方)
article//div选取所有属于article元素的后代的div元素,不管它出现在article之下的任何位置
//@class选取所有名为class的属性
/article/div[1]选取属于article子元素的第一个div元素
/article/div[last()]选取属于article子元素的最后一个div元素
/article/div[last()-1]选取属于article子元素的倒数第二个div元素
//div[@lang]选取所有拥有lang属性的div元素
//div[@lang='eng']选取所有lang属性为eng的div元素
/div/*选取属于div元素的所有子节点
//*选取所有元素
//div[@*]选取所有带属性的div元素
//div/a | //div/p选取所有div元素的a和p元素
//span | //ul选取文档中的span和ul元素
article/div/p | //span选取所有属于article元素的div元素的p元素 以及 文档中所有的span元素

        实例:

# -*- coding: utf-8 -*-
import scrapy
import re

class JobboleSpider(scrapy.Spider):
    name = 'jobbole'
    allowed_domains = ['blog.jobbole.com']
    start_urls = ['http://blog.jobbole.com/110287/']

    def parse(self, response):
        # 标题
        title = response.xpath("//*[@id='post-110287']/div[1]/h1/text()").extract()[0]
        # 发布日期
        create_date = response.xpath("//*[@id='post-110287']/div[2]/p/text()").extract()[0].strip().replace("·","").strip()
        # 点赞数
        praise_nums = response.xpath("//*[@id='110287votetotal']/text()").extract()[0]
        # 收藏数
        fav_nums = response.xpath("//*[@id='post-110287']/div[3]/div[8]/span[2]/text()").extract()[0]
        match_re = re.match(".*(\d+).*", fav_nums)
        if match_re:
            fav_nums = match_re.group(1)
        # 评论数
        comment_nums = response.xpath("//*[@id='post-110287']/div[3]/div[8]/a/span/text()").extract()[0]
        match_re = re.match(".*(\d+).*", comment_nums)
        if match_re:
            comment_nums = match_re.group(1)
        # 正文
        comment = response.xpath("//div[@class='entry']").extract()[0]

        # 标签
        tag_list = response.xpath("//*[@id='post-110287']/div[2]/p/a/text()").extract()
        tag_list = [element for element in tag_list if not element.strip().endswith("评论")]
        tags = ",".join(tag_list)

 

四、css选择器实现字段解析

    1、css选择器

表达式说明
*选择所有节点
#container选择id为container的节点
.container选取所有class包含container的节点
li a选取所有li下的所有a节点
ul + p选择ul后面的第一个p元素
div#container > ul选取id为container的div的第一个ul子元素
ul ~ p 选取与ul相邻的所有p元素
a[title]选取所有有title属性的a元素
a[href="http://jobbole.com"]选取所有href属性为jobbole.com值的a元素
a[href*="jobbole"]选取所有href属性包含jobbole的a元素
a[href^="http"]选取所有href属性值以http开头的a元素
a[href$=".jpg"]选取所有href属性值以.jpg结尾的a元素
input[type=radio]:checked选择选中的radio元素
div:not(#container)选取所有id非cintainer的div属性
li:nth-child(3)选取第三个li元素
tr:nth-chlid(2n)第偶数个tr

        实例:            

import scrapy
import re

class JobboleSpider(scrapy.Spider):
    name = 'jobbole'
    allowed_domains = ['blog.jobbole.com']
    start_urls = ['http://blog.jobbole.com/110287/']

    def parse(self, response):
        # 通过css选择器获取字段值
        # 标题
        title = response.css(".entry-header h1::text").extract()[0]
        create_date = response.css("p.entry-meta-hide-on-mobile::text").extract()[0].strip().replace("·", "").strip()
        # 点赞数
        praise_nums = response.css("#110287votetotal::text").extract()[0]
        # 收藏数
        fav_nums = response.css("span.bookmark-btn::text").extract()[0]
        match_re = re.match(".*?(\d+).*", fav_nums)
        if match_re:
            fav_nums = match_re.group(1)
        # 评论数
        comment_nums = response.css("a[href='#article-comment'] span::text").extract()[0]
        match_re = re.match(".*?(\d+).*", comment_nums)
        if match_re:
            comment_nums = match_re.group(1)
        # 正文
        contment = response.css(".entry::text").extract()[0]
        # # 标签
        tag_list = response.css("p.entry-meta-hide-on-mobile a::text").extract()
        tag_list = [element for element in tag_list if not element.strip().endswith("评论")]
        tags = ",".join(tag_list)

五、编写spider爬取jobbole的所有文章

# -*- coding: utf-8 -*-
import scrapy
import re
from scrapy.http import Request
from urllib import parse


class JobboleSpider(scrapy.Spider):
    name = 'jobbole'
    allowed_domains = ['blog.jobbole.com']
    start_urls = ['http://blog.jobbole.com/all-posts/']

    def parse(self, response):
        """
        1、获取文章列表中的文章url并交给scrapy下载后并进行解析;
        2、获取下一页的url并交给scrapy进行下载,下载完成后交给parse
        """
        # 解析列表页中的所有文章url并交给scrapy下载后进行解析
        post_urls = response.css("#archive .floated-thumb .post-thumb a::attr(href)").extract()
        for post_url in post_urls:
            # 有的href没有带域名,域名+href:response.url + post_url
            yield Request(url=parse.urljoin(response.url, post_url), callback=self.parse_detail)

        # 提取下一页并交给scrapy进行下载
        next_url = response.css(".next.page_numbers::attr(href)").extract_first("")
        if next_url:
            yield Request(url=parse.urljoin(response.url,next_url), callback=self.parse)

    def parse_detail(self, response):
        # 提取文章的具体字段
        # 通过css选择器获取字段值
        # 标题
        title = response.css(".entry-header h1::text").extract_first("")
        create_date = response.css("p.entry-meta-hide-on-mobile::text").extract_first("").strip().replace("·", "").strip()
        # 点赞数
        praise_nums = response.css(".vote-post-up h10::text").extract_first("")
        # 收藏数
        fav_nums = response.css("span.bookmark-btn::text").extract_first("")
        match_re = re.match(".*?(\d+).*", fav_nums)
        if match_re:
            fav_nums = int(match_re.group(1))
        else:
            fav_nums = 0
        # 评论数
        comment_nums = response.css("a[href='#article-comment'] span::text").extract_first("")
        match_re = re.match(".*?(\d+).*", comment_nums)
        if match_re:
            comment_nums = int(match_re.group(1))
        else:
            comment_nums = 0
        # 正文
        contment = response.css(".entry").extract()[0]
        # # 标签
        tag_list = response.css("p.entry-meta-hide-on-mobile a::text").extract()
        tag_list = [element for element in tag_list if not element.strip().endswith("评论")]
        tags = ",".join(tag_list)

六、items设计

七、数据表设计和保存

八、通过pipeline保存数据到mysql

九、scrapy item loader机制

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值