来自 威尼斯国际官方网站 2019-09-21 02:27 的文章
当前位置: 威尼斯国际官方网站 > 威尼斯国际官方网站 > 正文

【威尼斯国际官方网站】爬取简书专题,Python爬

  首先分明要爬取的笑话网址,笔者是直接百度笑话搜到的第一个网址,网站是,点进去开掘网页创设以作者之见依然相比较复杂的,由于照旧初学者,首先得先找到网页资源聚焦所在,搜索里面包车型客车法规,然后才好有针对性的爬取能源。对于那个网站,作者意识在左侧侧栏有多少个作弄大全的分类框。那几个看起来差不离蕴含了全站的文字笑话了。在这些分类框下有非常的多小的分类,点进小的分类后是此分类下的有着笑话网页列表,每一种网页里面含有部分嘲弄,大家最终是要把这贰个贰个网页里的笑话爬取存款和储蓄起来。


在简书中有相当多大旨频道,里面有恢宏雅观的篇章,小编想访谈那么些文章用于提取对作者有用的事物;

如实爬虫是多少个好的精选,小编选择了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/XH本田CR-V,当您在左边的网页中不停往上海滑稽剧团动的时候,就能持续冒出侧边新的链接,有未有开掘什么样?

那一个网页都以有规律的,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爬

关键词: