Python爬戏弄话存储在mysql里,爬取简书专项论题

作者: 网络编程  发布:2019-07-08

  首先鲜明要爬取的笑话网址,作者是直接百度笑话搜到的率先个网址,网站是,点步向发掘网页营造以作者之见依然相比较复杂的,由于仍旧初学者,首先得先找到网页能源集中所在,寻觅个中的法规,然后才好有指向的爬取能源。对于那个网址,作者发觉在侧边侧栏有二个嘲弄大全的分类框。那一个看起来大概包罗了全站的文字笑话了。在那几个分类框下有那几个小的归类,点进小的归类后是此分类下的享有笑话网页列表,每种网页里面含有部分笑话,我们最后是要把那三个多个网页里的嘲弄爬取存款和储蓄起来。


在简书中有好些个主旨频道,里面有大批量上佳的小说,笔者想访问那个著功能于提取对自己有用的事物;

确切爬虫是一个好的挑选,作者选拔了python的一个爬虫库scrapy,它的法定文书档案正是很好的教程:http://scrapy-chs.readthedocs.io/zh_CN/0.24/intro/tutorial.html

  爬取思路:爬取,获得多少个html页面,分析此html页面,获得分类框里的具备分类的url地址,遍历每七个分拣的url,爬取分类url的html网页,解析归类url网页,获得任何笑话网页列表,遍历笑话网页列表url,得到最后的涵盖二个一个吐槽的html页面,获嘲笑话,存储到mysql数据库。

  爬取我用的是Google浏览器,在这几个网址下按F12就足以见见网页源代码了,此时要分析那个笑话大全的分类框的组织,以便利用python正则表明式获取到大家想要的消息。

防微杜渐职业


scrapy安装

pip install Scrapy

笔者遇见的主题材料是,编写翻译时候stdarg.h找不到;于是查看报难点的头文件目录,把stdarg.h拷贝进去就OK了,这些花了作者好长期。。。

因为scrapy重视于twisted,所以有人安装scrapy大概会提醒缺乏twisted,介绍如下:

从https://pypi.python.org/pypi/Twisted/#downloads下载离线文件,然后施行一下安装。

tar jxvf Twisted-xxx.tar.bz2

cd Twisted-xxx

python setup.py install

图片 1

mysql

抓取到的数据暗中同意是用json存储,因为分裂种类的数量混合存款和储蓄,解析和查询过于繁琐,所以我选取数据库;至于未有用mongodb,是因为我电话上本来就有着mysql,何况本人攻读切磋用不到mongodb的部分独到之处。

mysql数据库是分服务器(server),客户端(workbench),python的接口链接器(mysql-connector);这几个都可以从官方找到,参见 https://dev.mysql.com/downloads/

connector能够直接用pip安装,这里有个平价便是不用额外操心处境变量的事宜。

pip install mysql-connector

对于connector的施用,参见官方认证文书档案:

https://dev.mysql.com/doc/connector-python/en/

图片 2

一个简约的框架


创设多少个scrapy工程

scrapy startproject HelloScrapy

启航多少个工程

scrapy crawl demo

还是能够用shell运营,那个收益是您能够涉足每叁个实施命令

scrapy shell ''

须求稳重的是,网站一般会有反爬虫机制,抓取会回去403错误,所以记得把user-agent改了:

settings.py

USER_AGENT = 'HelloWoWo'

开启爬虫

您必要在spider目录下创设叁个scrapy.Spider的子类,定义它的名称(name, 就是运行工程时钦定的名号),允许的域名(allowed_domains),初步的爬取链接(start_urls);

下一场定义parse函数,它的参数response正是响应内容,你能够从中剖判要拿走的原委和新的链接;解析的章程可以通过xpath和css,这里用xpath;然后能够经过yield,把解析到的靶子推送到存款和储蓄流程中,假诺你想爬虫系统持续爬取新的链接,也能够因此yield来走入下一步爬取中。

from HelloScrapy.items import HelloscrapyItem

class DemoScrapy(scrapy.Spider):

    name = 'demo'

    allowed_domains = ['jianshu.com']

    start_urls = [

        '',

        '',

    ]

    def parse(self, response):

        user_sel = response.xpath('//body/div/div/div/div/div/ul/li/div/p/text()')

        item = HelloscrapyItem()

        item['text_num'] = int(user_sel[0].extract())

        item['favor_num'] = int(user_sel[1].extract())

        yield item

Item

下面代码中的item便是用来描述抓取到的数据结构,它们每一个属性都用scrapy.Field()表示。

import scrapy

class HelloscrapyItem(scrapy.Item):

    # define the fields for your item here like:

    name = scrapy.Field()

    text_num = scrapy.Field()

    favor_num = scrapy.Field()

Pipeline

它承受整个存款和储蓄的历程,能够积存在json文件中,也得以透过数据库。

不过首先,你须要在settings.py中宣示你的pipeline(默许有的,展开注释然后修改下):

# Configure item pipelines

# See

ITEM_PIPELINES = {

  'HelloScrapy.pipelines.MySqlPipeline': 300,

}

假若选择最简便的json格局,能够定义如下:

其中open_spider,close_spider如名字同样,分别会在起步spider和终止spider时调用,所以那边分别定义了文件的打开和倒闭;

而process_item便是对各个item的储存管理,这里将item实行json化,保存在预订义的公文中。

import json

class HelloscrapyPipeline(object):

    def open_spider(self, spider):

          self.file = open('./items.txt', 'w')

    def close_spider(self, spider):

        self.file.close()

    def process_item(self, item, spider):

        line = json.dumps(dict(item))

        self.file.write(line)

        return item

本身那边使用的是mysql,介绍如下。

mysql

率先定义四个mysql的封装类,帮衬张开和关闭七个数据库,创造二个表,插入一条数据。

import mysql.connector

from mysql.connector import errorcode

from settings import *

class MySqlDb(object):

    def __init__(self, db_name):

        self.db_name = db_name

        self.cnx = None

        self.cursor = None

        pass

    def open(self):

        self.cnx = mysql.connector.connect(user=MYSQL_USER_NAME,        password=MYSQL_PASS_WORD)

        self.cursor = self.cnx.cursor()

        self.__ensureDb(self.cnx, self.cursor, self.db_name)

        pass

    def close(self):

        if self.cursor:

            self.cursor.close()

        if self.cnx:

            self.cnx.close()

        pass

    def createTable(self, tbl_ddl):

        if self.cnx and self.cursor:

            self.__ensureDb(self.cnx, self.cursor, self.db_name)

            self.__ensureTable(self.cursor, tbl_ddl)

            pass

    def insert(self, sql, values):

        if self.cnx and self.cursor:

            try:

                self.cursor.execute(sql, values)

                self.cnx.commit()

            except:

                pass

        pass

    def __ensureDb(self, cnx, cursor, db_name):

        try:

            cnx.database = db_name

        except mysql.connector.Error as err:

              if err.errno == errorcode.ER_BAD_DB_ERROR:

                  try:

                      cursor.execute("CREATE DATABASE {} DEFAULT CHARACTER SET 'utf8'".format(db_name))

                    except mysql.connector.Error as create_err:

                        print("Failed creating database: {}".format(create_err))

                        exit(1)

                    cnx.database = db_name

                else:

                    print err

                    exit(1)

    def __ensureTable(self, cursor, tbl_ddl):

        try:

            cursor.execute(tbl_ddl)

        except mysql.connector.Error as err:

            if err.errno == errorcode.ER_TABLE_EXISTS_ERROR:

                pass

            else:

                print err.msg

        else:

            pass

然后抽象一个item的基类:

该类的insertToDb定义了插入的长河,由各类子类提供创建表和插入数据的sql语句。

import scrapy

class BaseItem(scrapy.Item):

    def insertToDb(self, mysqldb):

            table_sql = self.getTableSql()

            insert_sql = self.getInsertSql()

            if table_sql and insert_sql:

                mysqldb.createTable(table_sql)

                mysqldb.insert(insert_sql, dict(self))

            else:

                print 'Empty!!!!!!!!!!!!!!!!!!!!!!!'

            pass

    def getTableSql(self):

        return None

    def getInsertSql(self):

        return None

它的二个子类暗暗提示:

import scrapy

from item_base import *

class ArticleItem(BaseItem):

    item_type = scrapy.Field()

    title = scrapy.Field()

    author = scrapy.Field()

    author_link = scrapy.Field()

    content = scrapy.Field()

    def getTableSql(self):

        return "CREATE TABLE `article` ("

            "  `title` varchar(256) NOT NULL,"

            "  `author` varchar(128) NOT NULL,"

            "  `author_link` varchar(1024) NOT NULL,"

            "  `content` TEXT(40960) NOT NULL,"

            "  PRIMARY KEY (`title`)"

            ") ENGINE=InnoDB"

    def getInsertSql(self):

        return "INSERT INTO article "

              "(title, author, author_link, content) "

              "VALUES (%(title)s, %(author)s, %(author_link)s, %(content)s)"

如此,爬取到的原委记录在分裂品类的item中,最终又经过item的insertToDb进度,插入到mysql中。

能够透过workbench直接查看:

图片 3

爬取本事

上边的中坚要素都有了,大家后续看下爬取进程中的一些小标题。

第一是怎么选拔xpath深入分析网页成分。

xpath重回的是selector,对应网页中的dom结构,比方大家用chrome调节和测量试验器看下网页的组织:

图片 4

当鼠标放置贰个地点,真实网页中会展现相应的选中区域的,所以您能够相比较左侧一斑斑找到它所对应的html结构,比方"//body/div/div/div"。

赢得属性方法应用@,如@href

xpath('div/div/span/@data-shared-at')

应用@class提取节点

response.xpath('//body/div[@class="note"]')

抓取html内容

content = article_sel.xpath("div[@class='show-content']/div[@class='show-content-free']/*").extract()

content = ''.join(content)

抓取文本

content = article_sel.xpath("div[@class='show-content']/div[@class='show-content-free']//text()").extract()

content = ''.join(content)

支持是怎么让爬虫延伸。

当你抓取到三个感兴趣的链接后,举个例子当前正值爬取的是某一个人的简书主页,网页中有广大稿子链接,你想继续爬取的话,就足以yield出去:

"""

url: 要继续爬取的链接

callback: 爬取后的响应管理

"""

yield scrapy.Request(url=link, callback=self.parse)

不过一般来看的链接是周旋地址,所以您要先做一个拍卖:

from urlparse import urljoin

link = urljoin('', link)

咱俩也看出,下边包车型客车self.parse方法被用在广大网页央求中,然而这个网页的格式只怕是不雷同的,那么你必要做三个分类:

cur_url = response.url

if cur_url.startswith(''):

    pass

elif cur_url.startswith(''):

    pass

末尾讲一下怎么去抓动态网页。

您能够剖判下简书有些专项论题的网页格式,它的开始和结果列表一般是10条,不过你往下滑动的时候它又会增多;当爬取那些专项论题网页的时候,你不得不深入分析最初步的10条,如何做吧?

开采调节和测量试验器,选用network/XHMurano,当你在左边手的网页中不停往上海好笑剧团动的时候,就能够四处出新右侧新的链接,有未有觉察怎么?

这个网页都以有规律的,xxx?order_by=added_at&page=xx,其中order_by正是以此专项论题的Tab目录,added_at表示最新扩大加的,而page正是第多少个页。

设若你遍历全部的page页,不就把那么些动态网页抓取到了呢?然而有个坏消息,正是page页有上限,近些日子是200,不要告诉是自己说的。。。

图片 5

  一般筛选内容都会采用对象内容组件的上层轻巧独一标志的机件,在这里本身采用了<div class=”joketype l_left”></div>这些html,那个div能够涵盖全体分类的原委,然后再拓展贰遍筛选就足以把具备url筛选出来了。到了分类子页面小编看了一晃url的原理,那一个分类的url都是/listXX_1.htm上马,发掘分类页面里面有个尾页的开关的url刚好是截止,而且url的.htm后面包车型客车特别数字递增,所以就很好爬取全部笑话页面了,至于提嘲讽话就不再多说了,直接上全数代码。

代码工程


代码笔者上传到了github上,个中HelloScrapy/db/settings.py中的变量是无用的,须要布置为可行的mysql用户名和密码。

https://github.com/callmejacob/spider

沉痛申明:

本文涉及的方法和代码都只用于学习和研商,严禁转发和用来商业指标,不然后果自负!

  mysql数据仓库储存款和储蓄模块代码,文件名叫mysql.py。

import pymysql

def insert(joke):
    #获取链接
    conn=pymysql.connect(host='127.0.0.1',user='root',passwd='123456',db='python')
    cur=conn.cursor()
    #sql语句,%s是占位符(%s是唯一的,不论什么数据类型都使用%s)防止sql注入
    sql='insert into joke(joke) VALUES(%s)'
    #params=('eric','wuhan') #参数 插入单条
    #li=[('a1','b1'),('a2','b2')] #批量插入参数
    #reCount=cur.execute(sql,params)
    reCount=cur.executemany(sql,joke) #批量插入
    conn.commit() #提交,执行多条命令只需要commit一次就可以
    cur.close()
    conn.close()

def get_one():
    #获取链接
    conn=pymysql.connect(host='127.0.0.1',user='root',passwd='123456',db='python')
    cur=conn.cursor()
    sql1='select number from number'
    reCount=cur.execute(sql1)
    number=cur.fetchone()[0] 1
    sql2='select joke from joke where id=%s'
    reCount=cur.execute(sql2,number)
    joke=cur.fetchone()[0]
    sql3='update number set number=%s where number=%s'
    params=(number,number-1)
    reCount=cur.execute(sql3,params)
    conn.commit()
    cur.close()
    conn.close()

本文由金沙澳门官网发布于网络编程,转载请注明出处:Python爬戏弄话存储在mysql里,爬取简书专项论题

关键词: 金沙澳门官网