欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

scrapy 中的xpath 和 css选择器

程序员文章站 2022-05-11 17:41:01
...

项目创建



1.	首先确定要爬取的网站,确定想要爬取的信息,分析页面结构和url。

以伯乐在线为例 http://python.jobbole.com/

2.	我们发现 http://blog.jobbole.com/all-posts/  这是所有文章
    那么我们不需要深度优先或广度优先的遍历算法了,因为all-posts就已经可以获取所有的url了。

3.
all-posts为第一页
http://blog.jobbole.com/all-posts/
http://blog.jobbole.com/all-posts/page/564/ 为564页
因为文章是增长的,所以最后的一页是不确定的,所以我们需要获取下一页

安装环境

pip install scrapy
如果安装出现错误 Failed building wheel for Twisted
手动下载 Twisted
https://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
下载完成后 pip install .\路径.whl

pip install scrapy
创建项目
scrapy startproject BoleOnline #伯乐在线

项目目录结构
└─BoleOnline
    │ scrapy.cfg
    │
    └─BoleOnline
        │  items.py
        │  middlewares.py
        │  pipelines.py
        │  settings.py
        │  __init__.py
        │
        ├─spiders
        │  │  __init__.py
        │  │
        │  └─__pycache__
        └─__pycache__
进入到目录 F:\code\bole_online_spider\BoleOnline\ 

创建一个爬虫应用
scrapy genspider bole blog.jobbole.com
                 名字  要爬取的网站主域名

在F:\code\bole_online_spider\BoleOnline\BoleOnline\spider
生成了一个 bole.py文件

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

    def parse(self, response):
        pass
        
启动命令 scrapy crawl bole
#windows下缺少包 pip install pypiwin32
pycharm 不能调试scrapy工程的,为了可以调试方便,我们编写一个main.py 程序入口

from scrapy.cmdline import execute

import sys
import os

sys.path.append(os.path.dirname(os.path.abspath(__file__)))
#os.path.abspath(__file__) 当前路径
# os.path.dirname 文件的父目录


# bole 对应 bole.py
execute(["scrapy","crawl","bole"])
启动前,将 robots协议  改为False
ROBOTSTXT_OBEY = False

xpath

8xpath节点的一些术语

父节点
子节点
同胞节点
先辈节点
后辈节点

xpath语法

表达式 说明
article 选取article元素所有子节点
/article 选取根元素 /article
article/a 代表 属于article的子元素,并且为a的节点
//div 获取所有div子元素
article//div article里面所有的div节点
//@class 获取所有属性为class的节点
/article/div[1] 获取article子元素为div的,第一个div元素
/article/div[last()] 最后一个
/article/div[last() -1 ] 倒数第二个
//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
class BoleSpider(scrapy.Spider):
    name = 'bole'
    allowed_domains = ['blog.jobbole.com']
    start_urls = ['http://blog.jobbole.com/114364/'] #

    def parse(self, response):

        // 获取 标题 发布时间 点赞、收藏、评论数
         
        pass

进入 shell 模式

scrapy shell http://blog.jobbole.com/114364/

利用xpath匹配标题 创建时间等

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

class BoleSpider(scrapy.Spider):
    name = 'bole'
    allowed_domains = ['blog.jobbole.com']
    start_urls = ['http://blog.jobbole.com/114364/'] #

    def parse(self, response):
        # 标题
        title = response.xpath('//*[@id="post-114364"]/div[1]/h1/text()').extract()[0]
        # 创建时间
        create_time = response.xpath('// *[ @id="post-114364"]/div[2]/p/text()[1]').extract()[0].strip().replace('·','').strip()
        # 点赞数
        like_nums = response.xpath('//span[contains(@class,"vote-post-up")]/h10/text()').extract()[0]
        # 收藏数
        collection_nums = response.xpath('//span[contains(@class,"bookmark-btn")]/text()').extract()[0]
        match_re = re.match(".*(\d+).*",collection_nums)
        if match_re:
            collection_nums = match_re.group(1)
        #评论数
        commens_nums = response.xpath('//a[@href="#article-comment"]/span/text()').extract()[0]
        match_re = re.match(".*(\d+).*", commens_nums)
        if match_re:
            commens_nums = match_re.group(1)

        # 提取正文(保留html格式 不做详细处理)
        content = response.xpath('//div[@class="entry"]').extract()[0]

        # 获取标签tag
        tag_list = [i  for i in response.xpath('//p[@class="entry-meta-hide-on-mobile"]/a/text()').extract() if not i.strip().endswith('评论')]
        tags = ",".join(tag_list)
        pass

css选择器

表达式 说明
* 选择所有节点
#container 选择id=container的节点
.container class = container的节点
li a li元素下 所有的a节点
ul + p 选择ul后边的第一个p元素(兄弟节点)
div#container > ul div<id=container> 中的 第一个ul (子元素)
ul ~ p 选取ul相邻的所有p元素
a[title] 有titile这个属性的所有a元素
a[href=“http://jobbole.com”]
a[href*=“jobbole”]
a[href^=“http”]
a[href$=".jpg"]
input[type=radio]:checked 选中状态的raido
div:not(#container) div id 不等于container
li:nth-child(3) 选取第3个li
tr:nth-child(2n) 第偶数个tr
scrapy shell
response.css(".entry-header h1::text").extract()
# ::是伪类选择器