美文网首页我爱编程Web虫虫
python入门-爬取动态网站

python入门-爬取动态网站

作者: Swifer | 来源:发表于2018-04-18 21:24 被阅读186次

    一、缘起

    跟林同学一起学了 python 一周左右的时候,她开始做她的毕业设计,去爬一个网站
    由于我们都还没接触过动态网站(这里简单的认为是用 ajax 去加载数据的),所以用爬静态网站的方法肯定行不通啦。
    然后我查了一小时才发现是数据是动态加载的(真够菜的。。)

    二、过程

    后来查查资料,发现爬动态网站常用的就几种方法:
    1,分析 ajax 请求、参数等,用爬静态网站的方法,直接拿 json 数据。
    2,使用 splash 爬取
    3,使用 selenium 模拟鼠标操作,去爬取相关数据
    第一种方法比较简单,只是分析请求稍微有点费时。林同学用半个小时就用 scrapy 搞定了,才几行代码而已。。

    
    import requests
    
    url = 'http://app.gdstc.gov.cn/sjkf/kjxm'
    data = {
        'const_dict_id': 10203,
        'start': 60,
        'length': 30,
    }
    headers = {'User-Agent': 'Mozilla/5.0(Macintosh;IntelMacOSX10.6;rv:2.0.1)Gecko/20100101Firefox/4.0.1',
               "Cookie": "BAIDUID=4650B0B34048BBAA1E0B909B42F5A564:FG=1; BIDUPSID=4650B0B34048BBAA1E0B909B42F5A564; PSTM=1537177909; BDUSS=w0VmEzUFFWTTh0bld5VWVhNVo5MEEyV2ZKdTk3U2stMGZmWVQ1TTRuSnVkOHBiQVFBQUFBJCQAAAAAAAAAAAEAAAD0GzcNaG9uZ3F1YW4xOTkxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG7qoltu6qJbTk; pgv_pvi=6774493184; uc_login_unique=19e6fd48035206a8abe89f98c3fc542a; uc_recom_mark=cmVjb21tYXJrXzYyNDU4NjM%3D; MCITY=-218%3A; cflag=15%3A3; SIGNIN_UC=70a2711cf1d3d9b1a82d2f87d633bd8a02893452711; locale=zh; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1539333192; from_lang_often=%5B%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%2C%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%5D; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; to_lang_often=%5B%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%2C%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%5D; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1539333307",
               }
    response = requests.get(url, params=data, headers=headers, timeout=10)
    print(response.url)
    print(response.status_code)
    
    if response.status_code == 200:
        content = response.text
        print(content)
    

    然而,我用第二种方法,搞了两个小时,还只能拿到第一页的数据,无法拿到翻页的数据。林同学为她拿到数据而开心的时候,我还在很烦躁地 debug。。
    后来,我用了第三种方法,终于还是搞定了。代码如下:

    import re
    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from bs4 import BeautifulSoup
    import pymysql
    
    
    #创建连接
    conn = pymysql.connect(
        host='localhost', #主机名
        port=3306,        #端口号(默认的)
        user='root',  #用户名
        passwd='',   #密码
        db='technology',  #数据库名,需要先自己手动新建
        charset='utf8', #这里设置编码是为了输出中文
    )
    #获取cursor
    cur = conn.cursor()
    browser = webdriver.Chrome()
    wait = WebDriverWait(browser, 10)
    url = "http://app.gdstc.gov.cn/app/sjkf/kjxm_10203.jsp"
    
    
    def start():
        print('--started--')
        try:
            browser.get(url)
            # 等待 ajax 加载完成
            numbers = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#listTable_paginate > ul > li:nth-child(8) > a")))
            get_infos()
            return numbers.text
        except TimeoutError:
            return start()
    
    
    def next_page(page_number):
        print('--paging--')
        try:
            # 模拟点击下一页
            next = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#listTable_next > a")))
            next.click()
            # 等待 ajax 刷新完成
            wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR,"#listTable_paginate > ul > li.paginate_button.active"), str(page_number)))
            get_infos()
        except TimeoutError:
            next_page()
    
    
    def get_infos():
        wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#listTable_wrapper #listTable")))
        html = browser.page_source
        soup = BeautifulSoup(html, "html.parser")
        trs = soup.select("tr[role='row']")
        for tr in trs[1:]:
            info = []
            for td in tr:
                # print(td.text)
                info.append(td.text)
            save_to_mysql(info)
    
    
    # 需要自己先手动建一个 infos 的表,关有相关字段
    def save_to_mysql(info):
        sql = "insert into infos (name, location, firstTime, validTime) values ('%s', '%s', '%s','%s')" % (info[0], info[1], info[2], info[3])
        try:
            # 执行sql语句
            cur.execute(sql)
            # 提交到数据库执行r
            conn.commit()
        except Exception as e:
            print('--Save To MYSQL Error--', e)
            # Rollback in case there is any error
            conn.rollback()
    
    
    def main():
        try:
            total = start()
            for i in range(2, int(total) + 1):
                next_page(i)
        except Exception as e:
            print('--Error Occurred--', e)
        finally:
            # 关闭数据库连接
            cur.close()
            conn.close()
            browser.close()
            print('--ended--')
    
    
    if __name__ == '__main__':
        main()
    
    

    学习视频

    三、后记

    写这篇文章主要是为了记录一下我枯燥的学习过程。

    四月份前两周主要在学机器学习,那时候觉得,要学的知识又多又难,我学习效率又低,智商也低,真的压力好大。可惜只坚持了两周就不行了。感觉比考研前一个月还累。晒一下前两周的学习时间表:


    学习时间表.png

    然后这几天主要在学 python 爬虫。
    入门 python 爬虫比入门机器学习简单一百倍。。于是现在经常睡到自然醒,无聊了就看电影,做条咸鱼,真是太舒服了。。

    相关文章

      网友评论

        本文标题:python入门-爬取动态网站

        本文链接:https://www.haomeiwen.com/subject/ecvbkftx.html