python爬取qq空间说说

模块:selenium,pyquery,json,time
使用的是:Chrome
遇到的问题:

  1. 模拟点击下一页操作,需要换方式。
  2. 遇到元素在frame,需要进入查找。

对空间的登陆进行分析

进入网址:https://i.qq.com/
说说地址:https://user.qzone.qq.com/{qq}/311

我模拟点击这个头像,也可以点击账号密码登陆,然后填充。
对头像点击右键检查审查元素

我们可以模拟点击这个标签的id进行模拟操作

        url = f'https://user.qzone.qq.com/{qq}/311'
        browser.get(url)
        try:
            browser.find_element(By.NAME, 'login_frame')  # 发现登陆的frame
        except:
            raise
        else:
            try:
                browser.switch_to_frame('login_frame')  # 发现之后进入login_frame
                login = wait.until(EC.element_to_be_clickable(
                    (By.ID, 'img_out_1290259791')))  # 获取点击按钮  也可以进行输入账号密码
                login.click()  # 进行点击
            except Exception as e:
                raise
        time.sleep(2)

在模拟登陆的时候:

  1. 直接寻找这个By.ID,img_out_1290259791是查找不到的,因为他在frame里面,所以browser.find_element(By.NAME, ‘login_frame’)进行判断发现。
  2. 然后再进入 browser.switch_to_frame(‘login_frame’)
  3. 然后才是模拟点击登陆

对说说进行分析

思路是:首先寻找说说有几页,然后在进行每页的跳转


这里就是说说的内容,发现这里也是一个frame,所以要进入,然后判断说说有几页。

browser.switch_to_frame('app_canvas_frame')  # 进入switch_to_frame
        page_last = wait.until(EC.presence_of_element_located(
            (By.CSS_SELECTOR, '#pager_last_0 > span'))).text  # 最后一页
        return int(page_last)

对说说内容进行分析

def get_page_text(n):
    try:
        doc = pq(browser.page_source)           # 获取页面的html
        items = doc('#msgList > li.feed').items()          # 获取所有的说说
        for item in items:      # 对说说进行分开
            yield {
                'time': item.find('div.box.bgr3 > div.ft > div.info > .c_tx3 > .c_tx').text(),
                'text': item.find('.content').text().lstrip('♡\n')
            }
        text = wait.until(EC.presence_of_element_located((By.ID, f'pager_go_{n-1}')))   # 获取跳转页的输入框
        text.send_keys(n+1)     # 输入下一页
        text.send_keys(Keys.ENTER)      #进行确定
    except:
        browser.close()

一开始模拟的点击下一页来进行爬去,但是遇到的问题是,

  1. 有的时候模拟点击的时候页面没有加载完毕,所以模拟点击的位置不在下一页
  2. 点击下一页了,没有跳转

所以换取了思路,进行跳转页的点击,知道了这一点以后,遇到爬页面的点击就不要模拟点击下一页了。
爬取的格式:

{"time": "12:42", "text": "一个男生如果真的爱你 无论多忙 都会腾出时间来陪你 他舍不得你胡思乱想 {uin:5289224,nick:查看全文,who:1}"}
{"time": "6:00", "text": " 我发现女孩子很容易被感动 喜欢的人说一句稍微宠溺一点的话 就开心的想把脸埋进被子里闷闷的笑出声 笑完又觉得丢脸 明明一大把年纪 还像个没爱过人的少女"}
{"time": "昨天23:07", "text": " 如果想我了 就抱抱空气吧 毕竟本可爱无处不在"}
{"time": "昨天23:07", "text": ""}
{"time": "昨天20:09", "text": "\"\"\" 他本是小小子国的质子,身份卑微,但是没关系。她喜 今夜,是她的新婚夜。 她披着凤冠霞帔,紧张又害怕。 最后她听到宫女们的声音,唤了一声驸马爷。 她知道,他来了,她的如意郎君魏君羡。欢他,喜欢这匹野马,一步步提携,最终胜任皇宫禁卫军统领,这才有资格成为她的驸马。 她从盖头的边缘看到了他的靴子,驻足在面前,却迟迟没有揭开盖头。 她正纳闷,没想到他吹熄了蜡烛,直接将她Tui到在chuang上,随后是si&che她的喜服。 嘶啦一声,她骤然一凉。 “君羡……”"}
{"time": "昨天13:47", "text": " 祝你喜欢的人恰巧也喜欢你 祝你每次考试都能有进步 祝你在下雨天时路上的空车都不拒载 祝你做过的美梦都不会忘记 祝你的心情永远像周五的下午 祝你永远活的像个孩子"}

完整的代码

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from pyquery import PyQuery as pq
import time
import json

options = webdriver.ChromeOptions()
#	设置无图模式
prefs = {
    'profile.default_content_setting_values': {
        'images': 2
    }
}
options.add_argument('--headless')          # 浏览器隐藏
options.add_argument('--disable-gpu')
options.add_experimental_option('prefs', prefs)        #设置无图模式
browser = webdriver.Chrome(chrome_options=options)
wait = WebDriverWait(browser, 5)


def get_last_page(qq):
    try:
        url = f'https://user.qzone.qq.com/{qq}/311'
        browser.get(url)
        try:
            browser.find_element(By.NAME, 'login_frame')  # 发现登陆的frame
        except:
            raise
        else:
            try:
                browser.switch_to_frame('login_frame')  # 发现之后进入login_frame
                login = wait.until(EC.element_to_be_clickable(
                    (By.ID, 'img_out_1290259791')))  # 获取点击按钮  也可以进行输入账号密码
                login.click()  # 进行点击
            except Exception as e:
                raise
        time.sleep(2)
        browser.switch_to_frame('app_canvas_frame')  # 进入switch_to_frame
        page_last = wait.until(EC.presence_of_element_located(
            (By.CSS_SELECTOR, '#pager_last_0 > span'))).text  # 最后一页
        return int(page_last)
    except Exception:
        get_last_page(qq)


def get_page_text(n):
    try:
        doc = pq(browser.page_source)           # 获取页面的html
        items = doc('#msgList > li.feed').items()          # 获取所有的说说
        for item in items:      # 对说说进行分开
            yield {
                'time': item.find('div.box.bgr3 > div.ft > div.info > .c_tx3 > .c_tx').text(),
                'text': item.find('.content').text().lstrip('♡\n')
            }
        text = wait.until(EC.presence_of_element_located((By.ID, f'pager_go_{n-1}')))   # 获取跳转页的输入框
        text.send_keys(n+1)     # 输入下一页
        text.send_keys(Keys.ENTER)      #进行确定
    except:
        browser.close()


def write_page(page):
    with open('qq.txt', 'a', encoding='utf-8') as f:
        for page in get_page_text(page):
            f.write(json.dumps(page, ensure_ascii=False) + '\n')       # 将dict转换为json格式进行保存


if __name__ == '__main__':
    page_last = get_last_page('qq')
    for i in range(1, page_last+1):
        write_page(i)
    browser.close()

你可能感兴趣的:(Python爬虫)