selenium爬取博客园文章保存到mysql并自动发布

发布时间:2019-02-23 15:02:11编辑:Run阅读(5119)

    分析目标网站:https://www.cnblogs.com/

    爬取的内容是编程语言里面的python技术文章

    image.png


    它这里是有js动态加载的标签,而且经过观察()里面的数字是会随机变化的,并不是写死的(推测是一种防爬虫策略)。

    如何解决呢?

    直接获取标签的text文本内容,然后在把text内容赋值给xpath(标签选择器),这样不管数字如何变化,得到的都是最新的数字,话不多说,直接上代码:

    from selenium import webdriver
    from selenium.webdriver.common.action_chains import ActionChains
    import time
    
    
    browser = webdriver.Chrome()
    http = 'https://www.cnblogs.com/'
    browser.get(http)
    browser.implicitly_wait(20)
    # 找到编程语言标签的content
    label_content=browser.find_element_by_xpath("//div[@id='cate_title_block']/ul/li[@id='cate_item_2']/a").text
    print(label_content)
    
    # 模拟鼠标悬停加载js,获取下级目录的标签
    label_xpath = "//div[@id='cate_title_block']//li/a[text()='{}']".format(label_content)
    print(label_xpath)
    ActionChains(browser).move_to_element(browser.find_element_by_xpath(label_xpath)).perform()
    
    
    # 找到python标签的content
    # 创建一个空的list,把text的值追加进来
    list_tmp = []
    list_new = []
    for i in browser.find_elements_by_xpath("//div[@class='cate_content_block']/ul/li/a"):
        list_tmp.append(i.text)
    # 去重和去除''内容
    for i in list_tmp:
        if i not in list_new and i != '':
            list_new.append(i)
    print(list_new)
    
    # 模拟点击python标签
    python_xpath = "//div[@class='cate_content_block']/ul/li/a[text()='{}']".format(list_new[4])
    browser.find_element_by_xpath(python_xpath).click()
    
    browser.quit()


    运行程序效果:

    1111.gif


    可以看到自动点击到python技术文章那里了,这样写不管编程语言(45)还是python(13),  ()里面的数字怎么变,都不会影响程序的运行。

    搞定了前面,接下来就是爬取对应文章的title和url了,这里还涉及到数据整合,优化上面的代码,加上日志功能,完整代码如下:

    from selenium import webdriver
    from selenium.webdriver.common.action_chains import ActionChains
    from mylog import MyLog as mylog
    import time
    
    
    class GetCnblogs:
        def __init__(self, url):
            self.log = mylog()  # 实例化mylog类,用于记录日志
            self.url = url
            self.browser = self.setup_browser(self.url)
            self.simulated_click(self.browser)
    
        def setup_browser(self, url):
            """
            打开目标网站 https://www.cnblogs.com/
            :return: browser
            """
            try:
                # 创建chrome参数对象
                browser = webdriver.Chrome()
                # 利用selenium打开网站
                browser.get(url)
                # 等待网站js代码加载完毕
                browser.implicitly_wait(20)
            except Exception as e:
                # 记录错误日志
                self.log.error('打开目标网站失败:{},错误代码:{}'.format(url, e))
            else:
                # 记录成功日志
                self.log.info('打开目标网站成功:{}'.format(url))
                # 返回实例化selenium对象
                return browser
    
        def simulated_click(self, browser):
            # 找到编程语言标签的content
            label_content = browser.find_element_by_xpath("//div[@id='cate_title_block']/"
                                                          "/ul/li[@id='cate_item_2']/a").text
            # 模拟鼠标悬停加载js,获取下级目录的标签
            label_xpath = "//div[@id='cate_title_block']//li/a[text()='{}']".format(label_content)
            ActionChains(browser).move_to_element(browser.find_element_by_xpath(label_xpath)).perform()
            # 找到python标签的content, 创建两个空的list
            list_tmp = []  # 临时的列表,用于保存text内容
            list_new = []  # 用于去重和去除''内容
            for i in browser.find_elements_by_xpath("//div[@class='cate_content_block']/ul/li/a"):
                list_tmp.append(i.text)
            # 去重和去除''内容
            for i in list_tmp:
                if i not in list_new and i != '':
                    list_new.append(i)
    
            # 模拟点击python标签
            python_xpath = "//div[@class='cate_content_block']/ul/li/a[text()='{}']".format(list_new[4])
            browser.find_element_by_xpath(python_xpath).click()
    
            # 获取文章title和url地址
            title_list = []
            url_list = []
            title_url_dict = {}
            for i in browser.find_elements_by_xpath("//div[@class='post_item']/div[@class='post_item_body']/h3/a"):
                title_list.append(i.text)
            for i in browser.find_elements_by_xpath("//div[@class='post_item']/div[@class='post_item_body']/h3/a"):
                url_list.append(i.get_attribute('href'))
            # 数据合并: title_list标题列表, url_list网站地址列表
            i = 1
            for x in title_list:
                title_url_dict.setdefault(i)
                title_url_dict[i] = {'title': x, 'url': None}
                i += 1
            s = 1
            for y in url_list:
                title_url_dict[s]['url'] = y
                s += 1
            # 记录title,url信息
            for i in title_url_dict:
                self.log.info("\n正在获取第{}篇文章\n标题为:{}\nURL地址:{}/"
                              "".format(i, title_url_dict[i]['title'], title_url_dict[i]['url']))
            time.sleep(5)
            browser.quit()
    
    
    if __name__ == '__main__':
        url = 'https://www.cnblogs.com/'
        st = GetCnblogs(url)

    pycharm运行截图

    image.png


    接下来获取每篇文章的具体内容,样式,图片

关键字