如题, 最近在使用 Selenium + Python 实现爬取数据的操作, 学学新姿势. 所以开一篇新的博客来记录一下. 先上个效果图直观感受下.

开始前的准备

参考资料:
https://blog.csdn.net/yangyangrenren/article/details/54137041

安装Python3

这个略过, 没装的自己去网上搜教程.

安装 Chrome 驱动

在 Chrome 帮助中查看当前自己浏览器的版本. (我更新到了最新的 71.0.3578.98) 然后去下面这个地址下载相对应的驱动(能用也仅有32位的). (注意这个网址被墙, 搭个梯子过去, 没梯子的邮件找我)

https://chromedriver.storage.googleapis.com/index.html

百度网盘
https://pan.baidu.com/s/10NKbgINZl33juS1HBBF9NA 提取码: 437v

下载好了以后把文件放到 Chrome 安装目录里去.

安装 Selenium

装好 Python 后在命令行里使用下面的命令安装

pip3 install -U selenium 

添加Chrome安装目录进Path

把Chrome目录添加进环境变量.


上述准备工作做完后, 用下面的代码测试下能不能使用驱动打开 Chrome

test.py

from selenium import webdriver
import os
import time
#引入chromedriver.exe
chromedriver = "C:/Program Files (x86)/Google/Chrome/Application/chromedriver.exe"
os.environ["webdriver.chrome.driver"] = chromedriver
browser = webdriver.Chrome(chromedriver)

#设置浏览器需要打开的url
url = "https://www.baidu.com/"
browser.get(url)

time.sleep(3)
browser.quit()

如果能正常打开就说明成功了. 接下来继续编程完成爬取数据的操作.


爬取数据

嘘. 本来想爬知乎的, 但是貌似知乎的程序员哥哥姐姐们做了限制, 反正, 还是算了. 换到36氪去爬吧. 当然, 做爬取的工作也是挺被人讨厌的, 所以要注意我们的程序不要刷的太快, 尽量多加点间隔, 不然会给其他人的工作带来麻烦.

不废话, 直接上代码. 什么? 解决思路? 本来想写的, 不过突然懒癌犯了, 给代码不是更直接吗. (๑ŐдŐ๑)



#coding:utf-8
from selenium import webdriver
import os
import time
import pymysql.cursors

class Crawler(object):
    def __init__(self):
        self.Chromedriver = "C:/Program Files (x86)/Google/Chrome/Application/chromedriver.exe"
        os.environ["webdriver.chrome.driver"] = self.Chromedriver
        self.Chrome = webdriver.Chrome(self.Chromedriver)

        # Connect to the database
        self.MySql = pymysql.connect(host='******.mysql.database.chinacloudapi.cn',
                                     user='******',
                                     password='******',
                                     db='news_36kr',
                                     charset='utf8',
                                     cursorclass=pymysql.cursors.DictCursor)

    def crawling36kr(self):
        url = "https://www.36kr.com/information/web_news"
        # 添加cookie前必须先打开一次网站
        self.Chrome.get(url)
        cookie = { "name" : "new_user_guidance", "value" : "true", "domain" : ".36kr.com"}
        self.Chrome.add_cookie(cookie)
        self.Chrome.get(url)
        time.sleep(3)

        item_list = self.Chrome.find_elements_by_class_name("kr-shadow-content")
        print("item_list = ", len(item_list))
        index = 0
        while index < len(item_list) - 1:
            item = item_list[index]
            index += 1
            item.location_once_scrolled_into_view
            imgSrc = item.find_element_by_class_name("scaleBig").get_attribute("src")
            title = item.find_element_by_class_name("article-item-title")
            path = title.get_attribute("href")
            print(index, " len = ", len(item_list), " img = " , imgSrc , " path = " , path, " title = ", title.text)

            self.news_detail_36kr(index, item)
            item_list = self.Chrome.find_elements_by_class_name("kr-shadow-content")
            time.sleep(2)

            if index == len(item_list) - 1:
                loading_more_button = self.Chrome.find_element_by_class_name("kr-loading-more-button")
                loading_more_button.location_once_scrolled_into_view
                time.sleep(3)
                item_list = self.Chrome.find_elements_by_class_name("kr-shadow-content")
                if index == len(item_list) - 1:
                    loading_more_button.click()
                    time.sleep(3)
                    item_list = self.Chrome.find_elements_by_class_name("kr-shadow-content")


    def news_detail_36kr(self, index, item):
        imgSrc = item.find_element_by_class_name("scaleBig").get_attribute("src")
        title = item.find_element_by_class_name("article-item-title")
        path = title.get_attribute("href")

        title.click()
        # select second page
        num = self.Chrome.window_handles
        self.Chrome.switch_to_window(num[1])
        time.sleep(5)
        # get content
        article_title = self.Chrome.find_element_by_class_name("article-title")
        author = self.Chrome.find_element_by_class_name("title-icon-item")
        summary = self.Chrome.find_element_by_class_name("summary")
        p_list = self.Chrome.find_elements_by_xpath("//*[@id='app']/div/div/div/div/div/div/div/div/div/div/div/div/div/div/div/p")
        print("article_title == ", article_title.text, " author = ", author.text, " summary = ", summary.text, " len(p_list) = ", len(p_list))
        content = ""
        for p in p_list:
            content += p.text
            print(content)

        # insert Data to db
        # try:
        try:
            with self.MySql.cursor() as cursor:
                # Create a new record
                sql = "INSERT INTO `corp_media` (`title`, `url`, `img`, `author`, `summary`, `content`) VALUES (%s, %s, %s, %s, %s, %s)"
                cursor.execute(sql, (article_title.text, path, imgSrc, author.text, summary.text, content))
            # connection is not autocommit by default. So you must commit to save your changes.
            self.MySql.commit()
        except Exception as e:
            print(e)

        time.sleep(3)
        self.Chrome.close()
        self.Chrome.switch_to_window(num[0])

if __name__ == "__main__":
     crawler = Crawler()
     crawler.crawling36kr() 

ok, 不到百行的代码, 有两点注意下, 打开 MySQL 数据库的操作使用 PyMySQL 这个库, 使用下面这个命令安装

pip3 install -U PyMySQL

数据库跟数据表自己去建, 反正我的是找同事要的 (我也不会建, 啊哈哈╰( ̄▽ ̄)╮) 贴一张他发给我的语句.

六个字段分别对应

title   文章标题
url     文章链接
img     文章封面
author  文章作者
summary 文章概要
content 文章内容

重复数据的问题, 我让同事帮忙用链接作为条件去重, 也就是说插入前判断如果数据库中有相同的链接就去掉.

插入到数据库成功后可以通过 Navicat Premium 这个软件查看. 分享一个官方版的注册码. 查看我的另一篇博客.