前言一、被抓二、源码总结
前言
上期说到我们爬取了长沙美食吧的一些帖子数据,但是发现有点问题。
长沙美食吧基本上都是打广告的,都是培训广告,没几个活人数据量太小了,一台机器奋斗一天才几千条数据,这是远远不够的
为了解决上述问题,访问了长沙吧进行调查。
一、被抓话说我回头想了想,数据爬取的慢的原因是因为每次翻页都需要点击完50个href链接才行,可是我需要的语料不就是长文本吗?标题已经给了,楼主说的内容,其实也展示了前200字,也就是说只要发帖人发布的内容不超过200字就不用点进去了。另外,其他人回复发帖人,会和问题有点关联,比如说某人发帖问哪里有好吃的,这个时候回复的人可能就是一个很好的答案。不过为了爬取速度,我还是决定不管了。那么现在的策略就是直接翻页了,速度是之前的50倍,一晚上一个小时就爬取了8000多条帖子。但是到了后面翻页翻不动了,总是给你d回首页,可能又是被抓了吧!
二、源码# -*- coding: UTF-8 -*- """ @狮子搏兔:2022/1/7 """ import random import time import asyncio import logging import tkinter import pandas as pd from pyppeteer import launcher import json from bs4 import BeautifulSoup from lxml import etree launcher.DEFAULT_ARGS.remove("--enable-automation") # 必须在 from pyppeteer import launch 去除浏览器自动化参数 from pyppeteer import launch def get_existdata(path): with open(path, "r", encoding='utf-8') as f: data = json.loads(f.read()) f.close() return data def getherf(html): dic = {} bsobj = BeautifulSoup(html, 'html.parser') content = bsobj.find_all('a', attrs={'class': "j_th_tit"}) intro = bsobj.find_all('div', attrs={'class': "threadlist_abs threadlist_abs_onlyline"}) if intro: intro = [b.text for b in intro] href = [] title = [] if content: href = [b['href'] for b in content] title = [b.text for b in content] if href: if href[0] == '/p/7552843831' or href[0] == '/p/7460502035': title.pop(0) href.pop(0) if href[0] == '/p/7552843831' or href[0] == '/p/7460502035': title.pop(0) href.pop(0) if len(title) == len(intro) and len(title) == len(href): for i in range(len(title)): dic[href[i]] = {'title': title[i], 'intro': intro[i]} return dic async def main(): # 浏览器 启动参数 start_parm = { # 启动chrome的路径 "executablePath": r"C:Program FilesGoogleChromeApplicationchrome.exe", # 关闭无头浏览器 "headless": False, "args": [ '--disable-infobars', # 关闭自动化提示框 '--window-size=1920,1080', # 窗口大小 '--log-level=30', # 日志保存等级, 建议设置越好越好,要不然生成的日志占用的空间会很大 30为warning级别 # '--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36', # UA '--no-sandbox', # 关闭沙盒模式 '--start-maximized', # 窗口最大化模式 # '--proxy-server=http://localhost:1080' # 代理 # r'userDataDir=D:project_demopython_demospider_demoJavascript 逆向系列课userdata' # 用户文件地址 ], } browser = await launch(**start_parm) page = await browser.newPage() tk = tkinter.Tk() width = tk.winfo_screenwidth() height = tk.winfo_screenheight() tk.quit() await page.setViewport(viewport={'width': width, 'height': height}) # 第二步,修改 navigator.webdriver检测 # 其实各种网站的检测js是不一样的,这是比较通用的。有的网站会检测运行的电脑运行系统,cpu核心数量,鼠标运行轨迹等等。 # 反爬js js_text = """ () =>{ Object.defineProperties(navigator,{ webdriver:{ get: () => false } }); window.navigator.chrome = { runtime: {}, }; Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'] }); Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5,6], }); } """ await page.evaluateOnNewdocument(js_text) # 本页刷新后值不变,自动执行js headurl = 'https://tieba.baidu.com/' # 内容url头部,用于拼接herf url = 'https://tieba.baidu.com/f?kw=%E9%95%BF%E6%B2%99&ie=utf-8&pn=' # 页数url头部 existdata = get_existdata('data/csb_data.json') # 读取目前有多少数据 startpage = 15000 num = len(existdata) // 50 * 50 # 计算应该跳到的页数 num = startpage if num == 0: num += 50 flag = True with open("data/newdata.json", "w", encoding='utf-8') as f: while num <= 988850: # 最大为19780页,每页50条数据 print('正在爬取第{}页'.format(num)) await page.goto(url + str(num)) # 访问herf页面 try: herftext = await page.content() # 获取html except baseException: continue contentdic = getherf(herftext) # 获取50条帖子的标题以及intro if len(contentdic) > 0: dic = {} for k in contentdic: # 去重 if k not in existdata: dic[k] = contentdic[k] if len(dic) > 0: f.write(json.dumps(dic, indent=0)) # 写入 time.sleep(random.randint(2, 5)) # 随机等待,单位秒 num += 50 # 翻页 f.close() # await browser.close() if "__main__" == __name__: asyncio.get_event_loop().run_until_complete(main())总结
下面就要去找个好用点的命名实体识别标注的工具了。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)