暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

入门Scrapy,爬了2345影视、毒汤一言和51日历的数据

IT敢客 2018-08-17
97

       最近在学习 Scrapy,学习的过程总是枯燥的,所以总要有些实例操作,才有兴趣继续学习!这里我爬了三个小项目。

1、爬取 2345 影视网站上的电视剧和电影资源

1.1 安装环境什么的就一笔略过了。需要的依赖包列表如下,你可以保存为一个 123.txt,然后pip install -r 123.txt
来安装这些依赖包。

  1. asn1crypto==0.24.0

  2. attrs==18.1.0

  3. Automat==0.7.0

  4. cffi==1.11.5

  5. constantly==15.1.0

  6. cryptography==2.3.1

  7. cssselect==1.0.3

  8. hyperlink==18.0.0

  9. idna==2.7

  10. incremental==17.5.0

  11. lxml==4.2.4

  12. mysqlclient==1.3.13

  13. parsel==1.5.0

  14. pyasn1==0.4.4

  15. pyasn1-modules==0.2.2

  16. pycparser==2.18

  17. PyDispatcher==2.0.5

  18. PyHamcrest==1.9.0

  19. pyOpenSSL==18.0.0

  20. pywin32==223

  21. queuelib==1.5.0

  22. Scrapy==1.5.1

  23. service-identity==17.0.0

  24. six==1.11.0

  25. Twisted==18.7.0

  26. w3lib==1.19.0

  27. zope.interface==4.5.0

如果有些包在 Windows 系统上可能安装不了,提示缺少 VC14 什么的,就单独下载 whl 格式的包安装。

1.2 新建一个 scrapy 项目

  1. scrapy startproject tv2345

建议用开发工具,我用的是 PyCharm 的 IDE,然后新建了一个项目,用的是 python 的 venv 环境!

在目录 tv2345/tv2345/spiders/下,新建一个 tv2345_spider.py 的文件。内容如下:

  1. import scrapy

  2. import re

  3.  

  4. class Tv2345Spider(scrapy.Spider):

  5.  

  6.    name = "tv2345"

  7.  

  8.    #start_urls = ['http://so.kan.2345.com/search_ 最新/']

  9.  

  10.    def start_requests(self):

  11.        yield scrapy.Request('http://so.kan.2345.com/search_ 神话/',

  12.                             callback=self.parse_tv2345,

  13.                             headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'},

  14.                             dont_filter=True,

  15.        )

  16.  

  17.    def parse_tv2345(self, response):

  18.  

  19.        for tv in response.css('div.item.clearfix'):

  20.            keyword = tv.css('span.sStyle::text').extract_first()

  21.            if keyword == '电视剧':

  22.                tmp_tv_name = tv.css('div.tit')

  23.                tv_name = tmp_tv_name.xpath('.//a/@title').extract_first()

  24.                tv_img = tv.xpath('.//img/@data-src').extract_first()

  25.                temp_tvs = tv.css('div.wholeTxt>div:last-child')

  26.                tv_url = temp_tvs.xpath('.//a/@href').extract()

  27.                dels = 'javascript:void(0);'

  28.                while dels in tv_url:

  29.                    tv_url.remove(dels)

  30.                tv_urls = tv_url

  31.                tv_nums = temp_tvs.xpath('.//a/@title').extract()  # [3:0]截取字段

  32.                yield {

  33.                   'tv_name': tv_name,

  34.                   'tv_img': tv_img,

  35.                   'tv_urls': tv_urls,

  36.                   'tv_nums': tv_nums,

  37.                }

  38.  

  39.            if keyword =='电影':

  40.                tmp_tv_name = tv.css('div.tit')

  41.                tv_name = tmp_tv_name.xpath('.//a/@title').extract_first()

  42.                tv_img = tv.xpath('.//img/@data-src').extract_first()

  43.                tmp_tv_urls = tv.css('div.playBtnCon.clearfix')

  44.                tv_url = tmp_tv_urls.xpath('.//a/@href')

  45.                tv_urls = tv_url.extract_first()

  46.                tv_nums = '播放'

  47.                yield {

  48.                    'tv_name':tv_name,

  49.                    'tv_img':tv_img,

  50.                    'tv_urls':tv_urls,

  51.                    'tv_nums':tv_nums,

  52.                }

  53.  

  54.        next = response.css('div.v_page a.last_child')

  55.        next_url = next.xpath('.//@href').extract_first()

  56.        if next_url:

  57.            next_url = response.urljoin(next_url)

  58.            yield scrapy.Request(next_url, callback=self.parse_tv2345)

上面分别对电视剧类型和电影类型做了单独的爬取规则,因为还有综艺等其他类型就不爬取了。

1.3 修改 setting.py 文件

  1. ITEM_PIPELINES = {

  2.    'tv2345.pipelines.tv2345Pipeline': 300,

  3. }

  4. USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.54 Safari/536.5'

  5. ROBOTSTXT_OBEY = False   #绕过 robots.txt

  6. FEED_EXPORT_ENCODING = 'utf-8'

1.4 爬取文件落地,以上是爬取电视剧神话电影神话的 Url,

  1. scrapy crawl tv2345 -t json -o tv234.json

然后查看 tv2345.json 的内容如下图所示

也可以用 json 格式化工具查看,更加清晰,推荐 json 格式化工具效果如下图所示


好了,以上还可以自定义导出 csv 等其他格式,如果需要导出 excel 格式,需要自定义写一下,默认不支持导出为 excel 格式。

2、爬取毒汤日历的语句,以及昨天和作者头像

2.1 新建一个 yiyan 的爬虫项目有

  1. scrapy startproject yiyan

2.2 在 yiyan/yiyan/spiders/目录下新建 yiyan_spider.py 文件,内容如下:

  1. # -*- coding:utf-8 -*-

  2. import scrapy

  3. import datetime

  4. import json

  5.  

  6.  

  7. class YiyanSpider(scrapy.Spider):

  8.    name = "yiyan"

  9.    start_urls = ['http://www.dutangapp.cn/u/toxic?date=2018-4-12']

  10.  

  11.  

  12.    def parse(self, response):

  13.        today = datetime.datetime.strptime('2018-08-17', '%Y-%m-%d')

  14.        fday = datetime.datetime.strptime('2018-04-12', '%Y-%m-%d')

  15.        contents = json.loads(response.body)

  16.        txts = contents['data']

  17.  

  18.        for txt in txts:

  19.            id = int(txt['id'])

  20.            content = txt['data']

  21.            at1 = str(txt['at'])

  22.            at = int(at1[:-3])

  23.            attime = datetime.datetime.fromtimestamp(at)

  24.            ct1 = str(txt['createTime'])

  25.            ct = int(ct1[:-3])

  26.            crtime = datetime.datetime.fromtimestamp(ct)

  27.            if txt['writer']:

  28.                nickname = txt['writer']['nick']

  29.                tximg = txt['writer']['avatar']

  30.            else:

  31.                nickname = ''

  32.                tximg = ''

  33.  

  34.            yield {

  35.                'id' : id,

  36.                'content': content,

  37.                'attime': attime,

  38.                'crtime': crtime,

  39.                'nickname': nickname,

  40.                'tximg': tximg,

  41.            }

  42.  

  43.        while today > fday:

  44.            fday = fday + datetime.timedelta(days=1)

  45.            date1 = str(fday)

  46.            next_url = "http://www.dutangapp.cn/u/toxic?date=" + date1

  47.            yield scrapy.Request(next_url, callback=self.parse)

由于是爬取 json 格式的内容,所以用到了 json!

说明:毒汤一言的 api 接口为http://www.dutangapp.cn/u/toxic?date=2018-8-17,后面加日期,会返回一串 json 格式的内容。如下所示

  1. {"total":3,"data":[{"id":1451,"data":"如果全世界都不要你了,你要记得还有我,我也不要你。","at":1534435200000,"by":4891,"from":null,"to":null,"type":null,"taste":1,"view":2299,"like":23,"say":4,"forward":9,"createTime":1528022185000,"audit":1,"status":1,"writer":{"id":4891,"nick":"凯哥哥 V5","avatar":"http://thirdwx.qlogo.cn/mmopen/vi_32/vCXR1tKSkwLqDW7rMziclFibMcUUDApBEib2R3qYbY4oLMTplkEP5T4FEeUEPrxlb4a9GTXatfGicCW4XbXT1brPdA/132","msgCount":null},"actions":[],"format":1,"viewStr":"上千人"},{"id":1027,"data":"不要再说自己是一条单身狗,其实,你可能比不上狗…","at":1534435200000,"by":5501,"from":null,"to":null,"type":null,"taste":1,"view":2350,"like":22,"say":2,"forward":3,"createTime":1526695986000,"audit":1,"status":1,"writer":{"id":5501,"nick":".","avatar":"http://thirdwx.qlogo.cn/mmopen/vi_32/WUndm7hBa1EtibmjNYO4TgN96ZlNrHwSiayAjPrBmomUp7OntwtjPeYvVBppsMqjd65iaVL7FyrxrtvN6BcmeAb4g/132","msgCount":null},"actions":[],"format":1,"viewStr":"上千人"},{"id":877,"data":"有些人出现在你的生活里,是想告诉你,你真好骗啊!","at":1534435200000,"by":4116,"from":null,"to":null,"type":null,"taste":1,"view":2236,"like":16,"say":2,"forward":8,"createTime":1526269165000,"audit":1,"status":1,"writer":{"id":4116,"nick":"Weirdo.","avatar":"http://thirdwx.qlogo.cn/mmopen/vi_32/ZrPfqw4AbHfY47VqKlUnZ7wxWQqbdp3J9x2wNzkNYpYX0BG5S3R6JMt2Eiawpdx9iaYzkXE27JNgsp5vhgSicrqUg/132","msgCount":null},"actions":[],"format":1,"viewStr":"上千人"}]}

2.3 增加导入到 Mysql 数据库,修改 settings.py

  1. ROBOTSTXT_OBEY = False

  2.  

  3. ITEM_PIPELINES = {

  4.    'yiyan.pipelines.YiyanPipeline': 300,

  5.    'yiyan.pipelines.YiyanEveryPipeline': 301,

  6.    'yiyan.pipelines.MySQLPipeline': 401,

  7. }

  8.  

  9. DEFAULT_REQUEST_HEADERS = {

  10.    "User-Agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36",

  11. }

  12. FEED_EXPORT_ENCODING = 'utf-8'

  13. MYSQL_DB_NAME = 'spydb'

  14. MYSQL_HOST = 'localhost'

  15. MYSQL_USER = 'spydb'

  16. MYSQL_PASSWORD = 'spydb'

  17. MYSQL_PORT = 3306

定义了数据和 User-Agent 等信息

2.4 修改 pipelines.py 文件,增加以下内容

  1. import MySQLdb

  2. class MySQLPipeline:

  3.    def open_spider(self, spider):

  4.        db = spider.settings.get('MYSQL_DB_NAME')

  5.        host = spider.settings.get('MYSQL_HOST')

  6.        port = spider.settings.get('MYSQL_PORT')

  7.        user = spider.settings.get('MYSQL_USER')

  8.        passwd = spider.settings.get('MYSQL_PASSWORD')

  9.  

  10.        self.db_conn = MySQLdb.connect(host=host,db=db,user=user,passwd=passwd,port=port,charset='utf8')

  11.  

  12.        self.db_cur = self.db_conn.cursor()

  13.  

  14.    def close_spider(self,spider):

  15.        self.db_conn.commit()

  16.        self.db_conn.close()

  17.  

  18.    def process_item(self,item,spider):

  19.        self.insert_db(item)

  20.        return item

  21.  

  22.    def insert_db(self,item):

  23.        values = (

  24.            item['id'],

  25.            item['content'],

  26.            item['attime'],

  27.            item['crtime'],

  28.            item['nickname'],

  29.            item['tximg'],

  30.        )

  31.        sql = 'insert into yiyan values (%s,%s,%s,%s,%s,%s)'

  32.  

  33.        self.db_cur.execute(sql,values)

这里是爬取了从 2018-04-12 到 2018-08-17 也就是今天的全部数据。自己去数据库建一张表!

2.5 爬取数据,并导入数据库

  1. scrapy crawl yiyan

2.6 查看数据库的内容

2.7 以后每天定时抓取一个当天的数据。

在 yiyan/yiyan/spiders/目录下,新建一个 yiyan_everyday_spider.py 文件,内容如下

  1. # -*- coding:utf-8 -*-

  2. import scrapy

  3. import datetime

  4. import json

  5.  

  6.  

  7. class YiyanEverySpider(scrapy.Spider):

  8.    name = "yiyan_every"

  9.    tdy = datetime.datetime.now().strftime('%Y-%m-%d')

  10.    tday = str(tdy)

  11.    url = "http://www.dutangapp.cn/u/toxic?date=" + tday

  12.    start_urls = [url]

  13.  

  14.  

  15.    def parse(self, response):

  16.        contents = json.loads(response.body)

  17.        txts = contents['data']

  18.  

  19.        for txt in txts:

  20.            id = int(txt['id'])

  21.            content = txt['data']

  22.            at1 = str(txt['at'])

  23.            at = int(at1[:-3])

  24.            attime = datetime.datetime.fromtimestamp(at)

  25.            ct1 = str(txt['createTime'])

  26.            ct = int(ct1[:-3])

  27.            crtime = datetime.datetime.fromtimestamp(ct)

  28.            if txt['writer']:

  29.                nickname = txt['writer']['nick']

  30.                tximg = txt['writer']['avatar']

  31.            else:

  32.                nickname = ''

  33.                tximg = ''

  34.  

  35.            yield {

  36.                'id' : id,

  37.                'content': content,

  38.                'attime': attime,

  39.                'crtime': crtime,

  40.                'nickname': nickname,

  41.                'tximg': tximg,

  42.            }

  43.  

  44.  

 

再次运行 scrapy crawl yiyan,会插入当天的数据!

3 爬取 51 万年历上面的数据

原理同上,就不再阐述了。主要是知道 51 万年历的 api 接口地址为http://www.51wnl.com/api/getdailysentenceweb.ashx?dt=2017-04-28,好了看一下最后的爬取结果。


举一反三:

       1、有了以上的数据,可以自己做一些 api 的接口出来,主要是防止其他网站不能访问的时候。

       2、如果将 scrapy 和 django 结合起来用,效果会更好,只传参数,数据不落地,但是目前还不知道怎么用。


文章转载自IT敢客,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论