歡迎光臨
每天分享高質量文章

Python爬蟲學習筆記總結(二)

五 資料庫儲存爬取的信息(MySQL)

爬取到的資料為了更好地進行分析利用,而之前將爬取得資料存放在txt檔案中後期處理起來會比較麻煩,很不方便,如果資料量比較大的情況下,查找更加麻煩,所以我們通常會把爬取的資料儲存到資料庫中便於後期分析利用。

這裡,資料庫選擇MySQL,採用pymysql這個第三方庫來處理python和mysql資料庫的存取,python連接mysql資料庫的配置信息

db_config ={
    'host''127.0.0.1',
    'port': 3306,
    'user''root',
    'password''',
    'db''pytest',
    'charset''utf8'
}

以爬取簡書首頁文章標題以及url為例,先分析抓取標的信息,

如上圖,文章題目在a標簽中,且url(href)只含有後半部分,所以在儲存的時候,最好把它補全。

mysql:新建一個資料庫pytest,建立一張名為titles的表,表中欄位分別為id(int自增),title(varchar),url(varchar),如下:

進行資料庫操作的思路為:獲得資料庫連接(connection)->獲得游標(cursor)->執行sql陳述句(execute)->事物提交(commit)->關閉資料據庫連接(close),具體代碼實現如下:

# -*- coding:utf-8 -*-

from urllib import request
from bs4 import BeautifulSoup
import pymysql

# mysql連接信息(字典形式)
db_config ={
    'host''127.0.0.1',
    'port'3306,
    'user''root',
    'password''',
    'db''pytest',
    'charset''utf8'
}
# 獲得資料庫連接
connection = pymysql.connect(**db_config)

# 資料庫配置,獲得連接(引數方式)
# connection = pymysql.connect(host='127.0.0.1',
#                        port=3306,
#                        user='root',
#                        password='',
#                        db='pytest',
#                        charset='utf8')


url = r'http://www.jianshu.com/'
# 模擬瀏覽器頭
essay-headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'
}
page = request.Request(url, essay-headers=essay-headers)
page_info = request.urlopen(page).read().decode('utf-8')
soup = BeautifulSoup(page_info, 'html.parser')
urls = soup.find_all('a''title')

try:
    # 獲得資料庫游標
    with connection.cursor() as cursor:
        sql = 'insert into titles(title, url) values(%s, %s)'
        for u in urls:
            # 執行sql陳述句
            cursor.execute(sql, (u.string, r'http://www.jianshu.com'+u.attrs['href']))
    # 事務提交
    connection.commit()
finally:
    # 關閉資料庫連接
    connection.close()


代碼執行結果:

六、Scrapy初體驗

之前大概學習了下通過urllib和Beautiful Soup 進行簡單資料爬取的流程,但是那隻適用於一些簡單的、資料量比較小的爬蟲專案,如果需要爬取的資料量比較大的話,之前的方法必定非常緩慢,所以就有了Scrapy,Scrapy是一個快速的web抓取框架,可抓取web站點並從頁面中提取結構化的資料。Scrapy給我們提供了許多的爬蟲基類,我們可以直接繼承使用,當然,既然Scrapy是一個框架,我們也可以根據自己的需要對它進行修改,下麵我們就慢慢來看Scrapy的使用。

(一)安裝(Windows)

Scrapy是純Python編寫的,所以需要一些比較重要的的Python依賴包:

  • lxml, an efficient XML and HTML parser

  • parsel, an HTML/XML data extraction library written on top of lxml,

  • w3lib, a multi-purpose helper for dealing with URLs and web page encodings

  • twisted, an asynchronous networking framework

  • cryptography and pyOpenSSL, to deal with various network-level security needs

看著依賴包比較多,其實安裝起來並不複雜,以管理員的身份運行Windows命令提示符,在以安裝Python的前提下,運行:

pip install scrapy

pip會自動下載相關依賴包,如果順利的話,會直接安裝完成。

要註意的是,確認一下python的版本,pip會根據系統自動安裝相關包,即如果系統是64位的,pip就會安裝64位的包,但是twisted的版本一定要和python的一樣,如果操作系統是64位的,python是32位的,pip直接安裝的twisted安裝就會出錯。

如果pip安裝twisted時出錯,在命令列輸入python,查看本地python版本,然後到這裡下載和python版本相同的whl檔案,使用pip install  xxx.whl安裝,完成後再執行一遍pip install scrapy即可。

在命令列輸入scrapy, 若不報錯,則安裝完成。

(二) 第一個Scrapy專案


照例,先上官方文件 1.3,找了一下網上翻譯的文件都是0.24或者0.24版,所以建議大家還是看官方最新的英文版比較好。

打開命令提示符,進入想要創建專案的目錄,運行

scrapy startproject scrapyTest

專案創建完成,讓我們來看一下專案結構,執行:

tree /f

└─scrapyTest
    │  scrapy.cfg           # 配置檔案(deploy configuration file)
    │
    └─scrapyTest
        │  items.py         # 專案中的item檔案(project items definition file)
        │  middlewares.py   # 中間件
        │  pipelines.py     # 專案中的管道檔案(project pipelines file)
        │  settings.py      # 專案中的設置檔案(project settings file)
        │  __init__.py
        │
        ├─spiders           # 存放爬蟲的檔案夾(a directory where you'll later put your spiders)
        │  │  __init__.py
        │  │
        │  └─__pycache__
        └─__pycache__

進入spiders目錄,新建test_spider.py如下:

# -*- coding:utf-8 -*-

import scrapy
from bs4 import BeautifulSoup


class tsSpride(scrapy.Spider):
    name = 'test' # 爬蟲的唯一名字,在專案中爬蟲名字一定不能重覆

    # start_requests() 必須傳回一個迭代的Request
    def start_requests(self):
        # 待爬取的URL串列
        urls = ['http://www.jianshu.com/',]
        # 模擬瀏覽器
        essay-headers = {'User-Agent''Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'}
        for url in urls:
            yield scrapy.Request(url=url, essay-headers=essay-headers, callback=self.parse)

    # 處理每個請求的下載響應
    def parse(self, response):
        soup = BeautifulSoup(response.body, 'html.parser')
        titles = soup.find_all('a''title')
        for title in titles:
            print(title.string)

在命令列輸入

scrapy crawl test

結果如下:

上述代碼Scrapy為start_requests 中的每個URL創建了scrapy.Request物件,並將 parse() 方法作為回呼函式(callback)賦值給了Request(Scray中parse()為預設回呼方法)。


七 Scrapy小例子

之前我們知道了Scrapy中每個檔案所代表的含義,這次我們就以爬取拉勾網Python相關招聘信息來具體演示下Scrapy每個檔案的用法。

我們要做的是,將拉勾網以‘Python’為關鍵字搜索到的招聘信息前五頁爬下來,然後將其中的‘職位’、‘薪資’、‘學歷要求’、‘工作地點’、‘公司名稱’以及‘信息發佈時間’提取出來並儲存到MySQL資料庫中。

(一)準備工作

我們先到拉勾網,在技術一欄中點擊Python,得到如下頁面:

點擊下一頁,觀察地址欄URL的變化:

第二頁的URL
https://www.lagou.com/zhaopin/Python/2/?filterOption=2

我們可以發現,頁碼的變化體現在URL中的兩個數字上,由此,我們便可以得到我們需要爬取的5個頁面的URL分別為:

urls = ['https://www.lagou.com/zhaopin/Python/1/?filterOption=1',
                'https://www.lagou.com/zhaopin/Python/2/?filterOption=2',
                'https://www.lagou.com/zhaopin/Python/3/?filterOption=3',
                'https://www.lagou.com/zhaopin/Python/4/?filterOption=4',
                'https://www.lagou.com/zhaopin/Python/5/?filterOption=5',
                ]

整理好需要爬取的URL後,我們來按F12打開開發者工具,找我們需要提取的信息:

可以看到需要爬取的信息都在

  • 標簽中沒,右鍵複製一個li標簽,整理一下格式,得到如下代碼:
  • class="con_list_item default_list" data-index="3" data-positionid="991482" data-salary="8k-16k" data-company="昆明俊雲科技有限公司" data-positionname="Python開發工程師" data-companyid="67804" data-hrid="1346958">
        <div class="list_item_top">
            <div class="position">
                <div class="p_top">

                    <a class="position_link" href="//www.lagou.com/jobs/991482.html" target="_blank" data-index="3" data-lg-tj-id="8E00" data-lg-tj-no="0104" data-lg-tj-cid="991482" data-lg-tj-abt="dm-csearch-useSalarySorter|1">

                    <h2 style="max-width: 180px;">Python開發工程師h2>


                    <span class="add">[<em>昆明·盤龍區em>
  • ]span>
                    <span class=“format-time”>1天前發佈span>
                div>

                <div class=“p_bot”>
                    <div class=“li_b_l”>
                        <span class=“money”>8k-16kspan>
                            經驗1-3年 / 本科
                    div>
                div>
            div>

            <div class=“company”>
                <div class=“company_name”>
                    <a href=“//www.lagou.com/gongsi/67804.html” target=“_blank” data-lg-tj-id=“8F00” data-lg-tj-no=“0104” data-lg-tj-cid=“67804” data-lg-tj-abt=“dm-csearch-useSalarySorter|1”>昆明俊雲科技有限公司a><i class=“company_mark”><span>該企業已上傳營業執照並通過資質驗證審核span>i>

                div>

                <div class=“industry”>
                    移動互聯網,硬體 / 初創型(不需要融資)
                div>
            div>

            <div class=“com_logo”>
                <a href=“//www.lagou.com/gongsi/67804.html” target=“_blank” data-lg-tj-id=“8G00” data-lg-tj-no=“0104” data-lg-tj-cid=“67804” data-lg-tj-abt=“dm-csearch-useSalarySorter|1”>![](//www.lgstatic.com/thumbnail_120x120/i/image/M00/58/0F/Cgp3O1fSFEuAQJnSAAATSLVt79k366.jpg)a>
            div>
        div>

        <div class=“list_item_bot”>
            <div class=“li_b_l”>
                <div class=“li_b_r”>
                “福利優厚、期權獎勵、五險一金、工作餐”
                div>
        div>
    li>

    可以發現,

  • 標簽屬性中有我們需要的’職位‘、’薪資‘、’公司名稱‘,而’工作地點‘、’學歷要求‘和’信息發佈時間‘則在下麵的各個標簽中,於是我們可以使用如下代碼,提取各個信息(Beautiful Soup):
  • info = BeautifulSoup(response.body, 'html.parser').find('li','con_list_item default_list')
     info.attrs['data-positionname'],  # 職位
    info.attrs['data-salary']
     info.find('em').get_text().split('·')[0],  # 工作地點
     (info.find('span''format-time')).string,  # 發佈時間
     info.find('div''li_b_l').get_text().split('/')[-1],  # 學歷要求
     info.attrs['data-company'],  # 公司名稱

    (二)資料庫的創建

    先來建好資料庫,這裡使用的是MySQL資料庫,建立如下:

    DROP TABLE IF EXISTS `info01`;
    CREATE TABLE `info01` (
      `id` int(11NOT NULL AUTO_INCREMENT,
      `title` varchar(255NOT NULL,
      `salary` int(255NOT NULL,
      `position` varchar(255NOT NULL,
      `time` varchar(255NOT NULL,
      `grade` varchar(255NOT NULL,
      `company` varchar(255NOT NULL,
      PRIMARY KEY (`id`)
    ENGINE=InnoDB AUTO_INCREMENT=498 DEFAULT CHARSET=utf8;

    要註意的是,其中的id屬性設為自增,’salary‘屬性設為int型別,方便以後進行資料分析統計。

    (三)代碼編寫


    準備工作完成了,下麵開始代碼部分,先到工作目錄中建立工程,在命令列中:

    scrapy startproject lgSpider

    先編輯items.py檔案,該檔案是一個簡單的資料收集容器,用於儲存爬蟲爬取的資料,類似一個字典:

    #  items.py
    # -*- coding: utf-8 -*-

    import scrapy

    class LgspiderItem(scrapy.Item):
        # define the fields for your item here like:
        # name = scrapy.Field()
        title = scrapy.Field()     # 職位
        position = scrapy.Field()  # 工作地點
        salary = scrapy.Field()    # 最低薪資
        company = scrapy.Field()   # 公司名稱
        time = scrapy.Field()      # 信息發佈時間
        grade = scrapy.Field()     # 學歷要求

    在spiders中建立爬蟲檔案lg_spider.py如下:

    # -*- coding:utf-8 -*-
    import scrapy
    from bs4 import BeautifulSoup


    class lg_spider(scrapy.Spider):
        name = 'lg'  # 爬蟲名字

        def start_requests(self):
            # 待爬取的url地址
            urls = ['https://www.lagou.com/zhaopin/Python/1/?filterOption=1',
                    'https://www.lagou.com/zhaopin/Python/2/?filterOption=2',
                    'https://www.lagou.com/zhaopin/Python/3/?filterOption=3',
                    'https://www.lagou.com/zhaopin/Python/4/?filterOption=4',
                    'https://www.lagou.com/zhaopin/Python/5/?filterOption=5',
                    ]
            # 模擬瀏覽器的頭信息
            essay-headers = {
                'User-Agent''Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'}
            for url in urls:
                yield scrapy.Request(url=url, essay-headers=essay-headers, callback=self.parse)

        def parse(self, response):
            # 使用Beautiful Soup進行分析提取
            soup = BeautifulSoup(response.body, 'html.parser')
            for info in soup.find_all('li''con_list_item default_list'):
                # 將提取的salary字串,只截取最少工資並轉換成整數形式,如:7k-12k  -> 7000
                salary = info.attrs['data-salary'].split('k')[0]
                salary = int(salary) * 1000
                # 儲存爬取的信息
                yield {
                    'title': info.attrs['data-positionname'],  # 職位
                    'position': info.find('em').get_text().split('·')[0],  # 工作地點
                    'salary': salary,  # 最低工資
                    'time': (info.find('span''format-time')).string,  # 發佈時間
                    'grade': info.find('div''li_b_l').get_text().split('/')[-1],  # 學歷要求
                    'company': info.attrs['data-company'],  # 公司名稱
                }

    爬取的item被收集起來後,會被傳送到pipelines中,進行一些處理,下麵開始編輯pipelines.py用於將爬取的資料存入MySQL資料庫,

    # -*- coding: utf-8 -*-

    import pymysql

    # 資料庫配置信息
    db_config = {
        'host''127.0.0.1',
        'port'3306,
        'user''root',
        'password''',
        'db''lg_info',
        'charset''utf8'
    }


    class LgspiderPipeline(object):
        # 獲取資料庫連接和游標
        def __init__(self):
            self.connection = connection = pymysql.connect(**db_config)
            self.cursor = self.connection.cursor()

        # Pipeline必須實現的方法,對收集好的item進行一系列處理
        def process_item(self, item, spider):
            # 儲存的SQL陳述句
            sql = 'insert into info01(title, salary, position, time, grade, company) values(%s, %s, %s, %s, %s, %s)'
            try:
                self.cursor.execute(sql, (item['title'].encode('utf-8'),
                                          item['salary'],
                                          item['position'].encode('utf-8'),
                                          item['time'].encode('utf-8'),
                                          item['grade'].encode('utf-8'),
                                          item['company'].encode('utf-8'),
                                          )
                                    )
                self.connection.commit()
            except pymysql.Error as e:
                # 若存在異常則丟擲
                print(e.args)
            return item

    最後,再來配置settings.py檔案,打開settings.py檔案,會發現其中有很多註釋,我們找到

    # Configure item pipelines

    它代表使用使用指定的pipeline,將其修改為如下格式:

    # LgspiderPipeline即我們寫的pipelines.py中的LgspiderPipeline類ITEM_PIPELINES = {   'lgSpider.pipelines.LgspiderPipeline': 300,
    }

    OK。所有工作都完成了,我們來執行一下爬蟲看一下效果;

    scrapy crawl lg

    掃清一下資料庫:

    現在我們就可以通過sql語言,進行簡單的資料統計,如找出所有最低工資高於10000的招聘信息:

    select * FROM info01 WHERE salary>10000

    '''
    作者:Veniendeavor
    鏈接:https://www.jianshu.com/p/2cc8310a51c4
    '''

    赞(0)

    分享創造快樂