python入门-爬取动态网站

一、缘起

跟林同学一起学了 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()

学习视频

三、后记

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

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


python入门-爬取动态网站_第1张图片
学习时间表.png

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

你可能感兴趣的:(python入门-爬取动态网站)