通过scrapy实现简单爬虫

版权声明:本文为博主原创文章,未经博主允许不得转载 https://blog.csdn.net/fangfu123/article/details/83792044

Scrapy概述

网络爬虫,大概很多人都听说过吧。
它是通过一定的规则,自动抓取互联网网站上的文章、信息、图片等等内容。
常见的应用就是搜索引擎。

而Scrapy则是实现网络爬虫的方式之一。

官方描述的Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。
可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。

Scrapy安装配置

Scrapy是需要配置Python环境的。所以我们先通过pycharm新建一个project。
配置git
然后安装环境:

pip install scrapy

pycharm并不支持直接创建scrapy的project,所以我们需要手动创建:

scrapy startproject SpiderProject

创建模板

scrapy提供了命令让我们可以根据模板创建spider,这个命令就是genspider
genspider可以直接创建spider的模板,比如我们爬www.ttsla.com

scrapy genspider ttsla www.ttsla.com

可以通过scrapy genspider -h 查看相关帮助
我们也可以通过scrapy genspider -l 查看可用模板

如果是windows下还需要装个win32模块:

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

调试运行

在命令行中调试选择器:

scrapy shell www.ttsla.com

这样我们就可以很方便的在命令行中通过response.css调试选择器,并把正确的调试结果copy到代码中。

实现简单的爬虫功能需要改三个文件:

settings.py
items.py
ttlsa.py

settings.py下需要设置ROBOTSTXT_OBEY,否则会过滤掉不符合ROBOTS协议的url:

ROBOTSTXT_OBEY = False

settings.py中还需要配置ITEM_PIPELINES,这一段代码默认是禁用的:

ITEM_PIPELINES = {
   'ttlsaSpider.pipelines.TtlsaspiderPipeline': 300,
}

item.py中定义爬虫爬取结果的结构,可以定义多个,比如标题定义类似于这种:

class TtlsaspiderItem(scrapy.Item):
    title = scrapy.Field()

ttlsa.py这个是我自定义的蜘蛛的名字,名字也可以是其他的,我这里只是示例。
如果我们之前执行了创建模板的命令,系统会自动生成这个文件。

其中的parse函数需要自己来写。要注意相互调用的关系。比如最简单的:

    def parse(self, response):
        item = TtlsaspiderItem()
        nodes = response.css(".entry-header .entry-title a")
        item['标题'] = nodes.css("::text").extract()
        yield item

注意在定义start_urls的时候,要配置好完整的url路径:

start_urls = ['http://www.ttlsa.com']

配好这三个文件,我们就可以scrapy crawl ttlsa -o result.csv来跑一下,
会自动生成一个csv文件
打开csv文件来验证结果。

取数据

通过网站的页面取数据有两种方法:xpath和css。
这两种取数据的方式各有优缺点,可以根据实际情况来分别应用。
通过xpath取出数据,示例如下:

title = response.xpath('//*[@class="grid-8"]/div[1]/div[1]/h1/text()').extract()

通过css取数据,示例如下:

title = response.css(".entry-header .entry-title a::text").extract()

response.xpath会返回一个SelectorList对象,extract后会把selector对象转换成list类型
如果取出来是一个list,可以通过selector[0]取出值.
xpath的值可以通过chrome浏览器的F12的调试功能找,然后把xpath复制出来。

下面是复杂一些的,取日期,其实方法是一样的:

date = response.xpath("//*[@class='entry-meta-hide-on-mobile']/text()").extract()[0].strip().replace("·", "").strip()

strip()方法是去空格和换行符;replace()方法是替换。

contains,我们加上contains,就是class中包含了‘vote-post-up’这个字符串就匹配了,代码如下:

response.xpath("//*[contains(@class, 'vote-post-up')]")

通常这种用法适合class包含了多个字符串的时候进行匹配。

有些时候需要通过正则来匹配,以下代码我们用xpath通过正则过滤掉了中文,只保留数字:

comments_nums = response.xpath("//a[contains(@href, '#article-comment')]/span/text()").extract()[0].strip()
match_re = re.match(".*?(\d+).*", comments_nums)
if match_re:
    comments_nums = match_re.group(1)

为了方便调试,我们可以自定义一个main.py,效果和命令行里输入命令是一样的:

from scrapy.cmdline import execute

execute(['scrapy', 'crawl', 'ttlsa'])

export

数据生成以后我们可以导出。我们需要修改pipelines.py的文件,可以通过pipeline将数据保存到json或数据库等。
Json的导出可以自定义方法,也可以使用自带的JsonItemExporter方法:

#使用scrapy内置JsonItemExporter的方法输出json
class JsonItemExporterPipeline(object):
    def __init__(self):
        self.file = open("result.json", "wb")
        self.export = JsonItemExporter(self.file, ensure_ascii=False, encoding='utf8')
        self.export.start_exporting()

    def close_spider(self):
        self.export.finish_exporting()

    def process_item(self, item, spider):
        self.export.export_item(item)
        return item

导出到数据库的方法也是类似的,我们以MySQL为例。我们首先需要装个mysqlclient
提供一个链接:
https://www.lfd.uci.edu/~gohlke/pythonlibs/#
这里有非常多适配windows的python库,搜一下mysql就能找出来,然后直接pip install
注意cp35代表python3.5的版本,win32代表32位的系统。
然后装mysql建库建表就不说了,我是直接用docker建库。建好表以后,可以增加设置一个id字段作为自增字段。
编写pipelines.py,添加自定义类,我这里就只两个字段:

class MysqlPipelines(object):
    def __init__(self):
        self.conn = MySQLdb.connect(host="192.168.99.100", user="root", passwd="root", port=3316, db="article_spider", charset="utf8", use_unicode=True)
        self.cursor = self.conn.cursor()

    def process_item(self, item, spider):
        insert_sql = """insert into ttlsa (title, url) values (%s, %s)"""
        self.cursor.execute(insert_sql, (item["title"], item["url"]))
        self.conn.commit()

注意修改settings.py里的配置文件

运行main.py调试。

猜你喜欢

转载自blog.csdn.net/fangfu123/article/details/83792044
今日推荐