分析目标网站:https://www.cnblogs.com/
爬取的内容是编程语言里面的python技术文章
它这里是有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()
运行程序效果:
可以看到自动点击到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运行截图
接下来获取每篇文章的具体内容,样式,图片