scrapy分页抓取网页( Scrapy爬虫框架和如何新建Python虚拟环境师列表和信息?)
优采云 发布时间: 2021-10-08 19:04scrapy分页抓取网页(
Scrapy爬虫框架和如何新建Python虚拟环境师列表和信息?)
目标和步骤
爬虫目标:从简单心理学网站获取心理咨询师名单和信息。
学习目标:
简单心理学网站有两种专家,“会诊”和“心理咨询师”。这里我们尝试先抓取顾问的信息。
顾问展示列表比较简单,总共有49页,每页有10个或11个顾问(有点棘手……)。只需抓取每个页面上的信息。
步骤分解:
新项目和爬虫
上一篇文章介绍了Scrapy爬虫框架以及如何新建Python虚拟环境。现在让我们创建一个新的 Scrapy 爬虫项目:
1
scrapy startproject jdxl
Scrapy 生成了以下文件
1
2
3
4
5
6
7
8
9
├── jdxl
│ ├── __init__.py
│ ├── items.py
│ ├── middlewares.py
│ ├── pipelines.py
│ ├── settings.py
│ └── spiders
│ └── __init__.py
└── scrapy.cfg
我们在蜘蛛文件夹中创建了一个新的爬虫文件顾问.py。
然后在items.py中定义要爬取的item:
1
2
3
4
5
6
7
8
9
class JdxlItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
name = scrapy.Field() #姓名
url = scrapy.Field() #链接
info = scrapy.Field() #简介
zx_type = scrapy.Field() #咨询类型
location = scrapy.Field() #地点
price = scrapy.Field() #价格
抓取页面信息
打开爬虫顾问.py,开始编写爬虫程序。
不要忘记先导入上面定义的对象:
1
from jdxl.items import JdxlItem
问题一:如何设置起始网址?
打开心理咨询师列表页面,然后翻到第二页,发现网址是一个很长的字符串:
1
https://www.jiandanxinli.com/experts?filter%5Bcity_id%5D=&filter%5Bfield_id%5D=&filter%5Bgender%5D=&filter%5Bonly_available%5D=&filter%5Bonly_junior%5D=&filter%5Bonly_online%5D=&filter%5Bprice%5D=&filter%5Bq%5D=&filter%5Bsect_id%5D=&filter%5Btarget_id%5D=&filter%5Btime%5D=&filter%5Btype_id%5D=&page=2
过滤参数在中间传递,只有最后一个&page=2是key。换句话说,被抓取页面的 URL 如下所示:
1
2
3
4
https://www.jiandanxinli.com/experts?&page=1
https://www.jiandanxinli.com/experts?&page=2
...
https://www.jiandanxinli.com/experts?&page=49
开始在 JdxlSpider(scrapy.Spider) 类中定义起始 URL:如下:
1
2
3
4
5
6
7
8
allowed_domains = ["jiandanxinli.com"]
start_urls = ['http://jiandanxinli.com/experts']
start_url_list = []
for i in range(1,50):
start_url_list.extend(['http://jiandanxinli.com/experts?&page=' + str(i)])
start_urls = start_url_list
问题二:如何抓取节点信息
在 def parse(self, response): 函数中定义要捕获的内容,并使用 XPath 语法告诉爬虫要捕获的节点位置。
什么是“怕死”?
XPath(XML 路径语言)是一种用于从 XML 文档中选择节点的查询语言。此外,XPath 可用于从 XML 文档的内容计算值(例如,字符串、数字或布尔值)。—— 维基
怎么写XPath?
感谢 Chrome,它直接提供了 XPath 选择功能。右键需要抓包的位置,点击Inspect,打开chrome-devtools面板:
瞄准要抓取的节点,再次右击,点击复制XPath,XPath路径就被复制了。
不要太高兴。无数次在调试坑中摔倒的00颤抖着告诉你:直接复制的XPath往往不能直接用...
比如上面那个顾问的名字,chrome提供的路径是:
1
//*[@id="content_wrapper"]/div[2]/div[2]/a[5]/div[1]/strong/text()
但更准确的路径是:
1
/div[@class="summary"]/strong/text()
.
对于初学者来说,如果之前没有太多写html和css的经验,每一个xpath都需要摸索很久。但这是唯一的出路。经过大量的折腾,您将学会诚实地阅读XPath 文档。
问题3:如果内容中没有节点怎么办?
当我抓到顾问的咨询方式、地点、价格等信息时,骗子就来了。
这个簇的结构是:
文字不收录在标签中!正面和背面都有一个 i 标签!怎么抓啊!
然后开始了漫长的谷歌之路。终于找到这篇文章:如何使用scrapy提取标签中没有的文本?
我通过follow::text()获取了一些信息:
1
2
3
zx_type = response.xpath('./div[@class="info"]/i/following::text()').extract()[1]
location = response.xpath('./div[@class="info"]/i/following::text()').extract()[2]
price = response.xpath('./div[@class="info"]/i/following::text()').extract()[3]
这样,每一列都不能有缺失的信息,否则爬取会错位... 暂且处理>。
问题4:如何抓取多个专家信息
抓取专家信息后,如何抓取每页10~11位专家信息?查看页面的html,每个专家都在标签下。因此,使用循环来获取具有此功能的所有标签。
为了缩小范围,在 response.xpath('//a[@class="expert"]') 中传递了父节点的路径。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
for each in response.xpath('//a[@class="expert"]'):
print(each)
item = JdxlItem()
# 抓取姓名
item['name'] = each.xpath('./div[@class="summary"]/strong/text()').extract()
# 抓取 url
item['url'] = each.xpath('./@href').extract()
# 抓取简介
item['info'] = each.xpath('./div[@class="summary"]//div[@class="content"]/text()').extract()
# 抓取咨询方式、地点、价格等
item['zx_type'] = each.xpath('./div[@class="info"]/i/following::text()').extract()[1]
item['location'] = each.xpath('./div[@class="info"]/i/following::text()').extract()[2]
item['price'] = each.xpath('./div[@class="info"]/i/following::text()').extract()[3]
yield item
其他配置
在settings.py文件中添加一个模拟user_agent的模块(需要先用pip安装faker包),设置爬取间隔、头信息等:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from faker import Factory
f = Factory.create()
USER_AGENT = f.user_agent()
# Obey robots.txt rules
ROBOTSTXT_OBEY = True
DOWNLOAD_DELAY = 1
DEFAULT_REQUEST_HEADERS = {
'Host': 'www.jiandanxinli.com',
'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'zh-CN,zh;q=0.8',
'Cache-Control': 'no-cache',
'Connection': 'Keep-Alive',
}
测试和抓取
开始爬行的命令是:
1
scrapy crawl counselor
Crawl 后面跟着 JdxlSpider(scrapy.Spider): 类中定义的爬虫名称。
尝试先获取 2 个页面:
1
2
for i in range(1,3):
start_url_list.extend(['http://jiandanxinli.com/experts?&page=' + str(i)])
调试过程中的主要问题是没有准确提供节点的xpath,没有抓取到内容。此外,您可能会忘记在 items.py 中设置项目。一般来说,根据错误报告,慢慢寻找,总能找到问题所在。耐心一点。
输出 csv
查了官方文档——Scrapy 1.4.0文档和Item Exporters——Scrapy 1.4.0文档中的Feed导出部分,尝试写pipelines,有点复杂并没有成功。
然后我搜索了Scrapy爬虫框架教程(二)——爬取豆瓣电影TOP250,只是在执行爬虫时设置输出参数:
1
scrapy crawl counselor -o output_file.csv
查看和清理数据
新建一个 Jupyter Notebook,导入 pandas 包,使用 pd.read_csv 命令查看文件:
获取的链接不完整,完整,输出:
1
2
df['url'] = 'http://jiandanxinli.com'+df['url']
df.to_csv('counselor.csv', index=False)
下一篇文章将继续介绍使用 Pandas 和 Bokeh 的简单数据统计和可视化。
项目源码请查看00的github repo:
参考