scrapy分页抓取网页(如何从OMIM抓取一些数据下来的网站数据下载的?)
优采云 发布时间: 2022-02-01 07:13scrapy分页抓取网页(如何从OMIM抓取一些数据下来的网站数据下载的?)
由于工作原因,我们需要从 OMIM 中获取一些数据。其实网站提供API和数据下载,但是对于营利单位来说,是需要权限的。无奈之下,只能求助于爬虫来解决。
什么是爬行动物
爬虫又称爬虫程序,是一种网络爬虫机器人,是一种模拟浏览器与网页交互的工具。它在英语中被称为“Bot”。例如,微软的爬虫,叫做“bingbot”,会定期对网页进行采样,发现新的或更新的网页,计算后决定是否加入索引。爬行动物的规模可大可小。像搜索引擎这样的大型爬虫会涉及大量机器和分布式组织。比如我今天用的那个小就是一台电脑,而不是手动输入400个网页和一堆复制粘贴操作。
爬虫的应用,除了上面提到的搜索引擎,还有数据分析。分析的数据不仅是自己产生的,也可能是从互联网上采集的。一些网站会提供数据采集接口,比如github、KEGG、NCBI和Ensembl,还有stackoverflow。一般来说,采集这些网站的数据要简单得多。直接根据自己的需要,按照它的接口规则拼出一个http URL就够了。在没有API的情况下从其他网站采集数据,需要依赖爬虫。如果你想搜索搜狗,你必须依靠自己的技术基础进行搜索。我做过知乎和微信搜索。我经常用这两个。在写一个主题之前,我需要做一个搜索。
在另一种情况下,不仅使用严格意义上的爬虫,还通过模拟浏览器行为。比如公司有一个网站系统出报告,但是做的时候没有给你留一个API接口,而是每次想到几十个网站,点击输入测试结果一个一、我想爆粗口,为什么不直接从服务器上传分析后的结果?这时候用的是模拟用户登录,选择跳转到指定样本的界面,分析POST请求参数,然后按要求完成参数,提交。这是用于自动化测试的,我稍后会写。
Scrapy 用途
关于Scrapy的安装和入门指南,官网文档的内容已经很不错了。这里我们以爬取OMIM网站为例介绍简单的用法和可能出现的问题。
def __init__(self, filename=None):
URL_BASE = 'https://www.omim.org/entry/'
if filename:
with open(filename, 'r') as f:
omim_ids = [re.findall(r'\((\d+)\)', line ) for line in f if line.startswith('chr') ]
self.start_urls = [ '{0}{1}'.format(URL_BASE, int(omim[0]) ) for omim in omim_ids if omim]
反爬虫反应
对于一些网站爬虫来说,比如Scrapy网站给出的例子,用猫画老虎可以达到目的,而OMIM不能。如果直接开始爬取,服务器会抛出403“拒绝访问”错误码。文档OMIM robots规定网站只允许Googlebot和bingbot抓取其指定目录下的数据。
关于反爬的反应,官网也有资料供参考:避免被封禁,参考这里和OMIM机器人,修改程序设置,然后测试顺利获取数据。使用的方法总结如下:
以下是程序代码:
#!/usr/bin/env python
#coding=utf-8
import re
import scrapy
class omimSpider(scrapy.Spider):
name = 'omim'
custom_settings = {
'USER_AGENT':'bingbot', #冒充bingbot的UA名和'BOT_NAME'
'BOT_NAME':'bingbot',
'COOKIES_ENABLED':False,
'DOWNLOAD_DELAY':4
}
def __init__(self, filename=None):
URL_BASE = 'https://www.omim.org/entry/'
if filename:
with open(filename, 'r') as f:
omim_ids = [re.findall(r'\((\d+)\)', line ) for line in f if line.startswith('chr') ]
self.start_urls = [ '{0}{1}'.format(URL_BASE, int(omim[0]) ) for omim in omim_ids if omim]
# self.start_urls = ['https://www.omim.org/entry/131244']
def parse(self, response):
gene_pheno = {}
gene_pheno['url'] = response.url
gene_pheno['omim_num'] = re.findall(r'(\d+)',response.url)[0]
#extract from Description
if 'Description' in response.text:
gene_pheno['description'] = ','.join(response.xpath('//div[@id="descriptionFold"]/span/p/text()').extract() )
#extract from table
if response.xpath('//table'):
tr = response.xpath('//table/tbody/tr') #maybe one or more trs
gene_pheno['location'] = tr[0].xpath('td')[0].xpath('span/a/text()').extract_first().strip() #first td of first tr in table
phenotype = tr[0].xpath('td')[1].xpath('span/text()').extract_first().strip()
mim = tr[0].xpath('td')[2].xpath('span/a/text()').extract_first()
inherit = ','.join(tr[0].xpath('td')[3].xpath('span/abbr/text()').extract() )
pheno_key = tr[0].xpath('td')[4].xpath('span/abbr/text()').extract_first()
gene_pheno[mim] = [phenotype, inherit, pheno_key]
if len(tr) > 1:
for tb_record in tr[1:]: #less num of column than the tr above
phenotype = tb_record.xpath('td')[0].xpath('span/text()').extract_first().strip()
min = tb_record.xpath('td')[1].xpath('span/a/text()').extract_first()
inherit = ','.join(tb_record.xpath('td')[2].xpath('span/abbr/text()').extract() )
pheno_key = tb_record.xpath('td')[3].xpath('span/abbr/text()').extract_first()
gene_pheno[mim] = [phenotype, inherit, pheno_key]
return gene_pheno
指示
#scrapy 版本 1.1.0
scrapy runspider omim.py -o all_omim.json -a filename=/path/to/file.txt
参考:
Scrapy官网文档
w3school xpath 文档
omim.py 源代码
/r/tETI0BDESU02rVSz9xGm(二维码自动识别)