问题描述

爬取今日头条作者的全部文章,这里以我室友的头条号(紫醉金迷)为例。今日头条作者页面的文章列表是js加载的,但具体的文章内容是HTML。判断用Chrome浏览器,设置里面禁用JavaScript,重新加载,如果页面只加载部分,则未加载部分采用Ajax加载。

解决

本篇文章采用Selenium模拟浏览器,BeautifulSoup内容抓取,具体内容文章可以用Requests库,但这里只爬一个人的,就不考虑效率问题了,都用Selenium。

爬取作者的全部文章链接

先配置好Selenium后,打开作者的url,要获取Ajax内容,这里有两个思路。

  1. 模拟浏览器不停的下拉,driver.execute_script('window.scrollTo(0, document.body.scrollHeight)'),但这种方法经常加载不了,而且driver.page_source的内容不变
  2. 模拟按键DOWN,不停的加载,直到全部加载完,保存page_source,简单粗暴。

    def get_urls(url):
    driver.get(url) #打开网址
    time.sleep(1)
    driver.refresh() #这里要刷新一下,不然第一次加载没反应
    driver.implicitly_wait(2) #隐性等待2秒
    for i in range(10000): #这里循环次数尽量大,保证加载到底
        ActionChains(driver).key_down(Keys.DOWN).perform() #相当于一直按着DOWN键
        print(f'已完成{i}次')
    time.sleep(3)
    soup = BeautifulSoup(driver.page_source, 'html.parser')
    body = soup.find_all(class_='link title') #提取网址
    for i in range(len(body)):
        url = 'https://www.toutiao.com' + body[i].get('href')
        print(f'已完成{i}个')
        with open('urls.txt', 'a') as f: #把网址按行保存到urls.txt
            f.writelines(url)
            f.write('\n')
    driver.quit()
    
    爬取文章的标题,作者,发布时间,正文

    这个就很简单了,把urls.txt中的网址,一个一个打开,获取内容。

    def get_htmls():
    with open('urls.txt', 'r') as f:
        urls = f.readlines()
    l = len(urls)
    htmls = []
    for i in range(l):
        print(urls[i])
        driver.get(urls[i])
        driver.execute_script('window.scrollTo(0, document.body.scrollHeight)') #加载到底部,保证图片文章中的图片加载完
        soup = BeautifulSoup(driver.page_source, 'html.parser')
        try: #如果异常,刷新一下
            body = str(soup.find_all(class_='article-title')[0]) + str(soup.find_all(
                class_='article-sub')[0]) + str(soup.find_all(class_='article-content')[0]) #获取标题,时间,正文
        except IndexError:
            driver.refresh()
            time.sleep(2)
        if not os.path.exists('htmls'):
            os.mkdir('htmls')
        with open(f'htmls/{i}.html', 'w') as f: #保存到htmls文件夹下
            f.write(body)
        print(f'{i}.html 完成, 共{l}个')
        time.sleep(3)
    driver.quit()
    
    把html转换为markdown或pdf格式

    完整代码详见 https://github.com/itswcg/crawler-toutiao, 欢迎点赞。