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()
# ::是伪类选择器
上一篇: 51nod 2020
下一篇: 数据库查询有关问题