爬取Whatsapp群链接
一、JS客户端单页爬虫1、定位爬取标签因为该爬虫是要覆盖不同网页,所以不能通过特殊标识来定位标签,只能将所有的a标签爬出来然后对href的内容进行一定的筛选。//预定列表头var linklist = [['链接']]//获取所有的a标签var links = document.getElementsByTagName('a');for(var link of links){//筛选出以https
一、JS客户端单页爬虫
1、定位爬取标签
因为该爬虫是要覆盖不同网页,所以不能通过特殊标识来定位标签,只能将所有的a标签爬出来然后对href的内容进行一定的筛选。
//预定列表头
var linklist = [['链接']]
//获取所有的a标签
var links = document.getElementsByTagName('a');
for(var link of links){
//筛选出以https://chat.whatsapp.com/为开头的a标签
if (link.href.startsWith('https://chat.whatsapp.com/')){
//将符合要求的链接添加进列表
linklist.push([link.href]);
}
}
//使用set对列表元素去重
linklist = [...new Set(linklist)]
2、使用xlsx.js工具包
xlsx.js工具包可以直接在前端通过js将数据保存为excel文件。
(1)动态载入js文件
var myScript= document.createElement("script");
myScript.type = "text/javascript";
//在此处引用了其他网站的xlsx.js包,不安全,不确定会不会失效
myScript.src = 'https://demo.haoji.me/2017/02/08-js-xlsx/js/xlsx.core.min.js';
document.body.appendChild(myScript);
(2)定义工具函数
sheet2blob
function sheet2blob(sheet, sheetName) {
sheetName = sheetName || 'sheet1';
var workbook = {
SheetNames: [sheetName],
Sheets: {}
};
workbook.Sheets[sheetName] = sheet;
var wopts = {
bookType: 'xlsx',
bookSST: false,
type: 'binary'
};
var wbout = XLSX.write(workbook, wopts);
var blob = new Blob([s2ab(wbout)], {type:"application/octet-stream"});
function s2ab(s) {
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
return blob;
}
openDownloadDialog
function openDownloadDialog(url, saveName) {
if(typeof url == 'object' && url instanceof Blob)
{
url = URL.createObjectURL(url);
}
var aLink = document.createElement('a');
aLink.href = url;
aLink.download = saveName || '';
var event;
if(window.MouseEvent) event = new MouseEvent('click');
else
{
event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
}
aLink.dispatchEvent(event);
}
(3)保存为excel
保存excel操作的前提是需要xlsx.js工具包已经加载完成,所以保存文件的操作需要在onload
函数内使用。
myScript.onload = function (){
var sheet = XLSX.utils.aoa_to_sheet(linklist);
openDownloadDialog(sheet2blob(sheet), 'grouplink.xlsx');
}
3、完整代码
var myScript= document.createElement("script");
myScript.type = "text/javascript";
myScript.src = 'https://demo.haoji.me/2017/02/08-js-xlsx/js/xlsx.core.min.js';
document.body.appendChild(myScript);
myScript.onload = function (){
function sheet2blob(sheet, sheetName) {
sheetName = sheetName || 'sheet1';
var workbook = {
SheetNames: [sheetName],
Sheets: {}
};
workbook.Sheets[sheetName] = sheet;
var wopts = {
bookType: 'xlsx',
bookSST: false,
type: 'binary'
};
var wbout = XLSX.write(workbook, wopts);
var blob = new Blob([s2ab(wbout)], {type:"application/octet-stream"});
function s2ab(s) {
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
return blob;
}
function openDownloadDialog(url, saveName) {
if(typeof url == 'object' && url instanceof Blob)
{
url = URL.createObjectURL(url);
}
var aLink = document.createElement('a');
aLink.href = url;
aLink.download = saveName || '';
var event;
if(window.MouseEvent) event = new MouseEvent('click');
else
{
event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
}
aLink.dispatchEvent(event);
}
var linklist = [['链接']]
var links = document.getElementsByTagName('a');
for(var link of links){
if (link.href.startsWith('https://chat.whatsapp.com/')){
linklist.push([link.href]);
}
}
linklist = [...new Set(linklist)]
var sheet = XLSX.utils.aoa_to_sheet(linklist);
openDownloadDialog(sheet2blob(sheet), 'grouplink.xlsx');
}
二、Google搜索结果爬虫
服务端爬虫使用了python的scrapy爬虫框架,该框架封装了一些爬虫方法,可以比较方便的完成爬虫工作。
1、创建scrapy项目
在linux上安装scrapy十分容易,但在windows上安装可能会遇到Microsoft Visual C++ 14.0 is required
这样的报错,解决办法见Microsoft Visual C++ Build Tools下载/解决Visual C++ 14.0 is required问题。
接下来按照官方教程创建grouplink爬虫项目。
scrapy startproject grouplink
cd grouplink
2、实现Google爬虫
本次爬虫的需求是通过运营给定的一系列关键词从Google的搜索结果的网页中爬取WhatsApp的群链接。这就涉及到两个点,第一是对Google搜索结果网页的爬取,第二是对搜索结果网页中的群链接爬取,最后的结果只需得到群连接。
(1)定义Item
item的作用在我的理解上来说是将爬虫爬取到的数据暂存下来,方便以后使用。
items.py
import scrapy
class GrouplinkItem(scrapy.Item):
link = scrapy.Field()
(2)新建grouplinkspider.py文件
在grouplink项目下的spiders文件夹新建grouplinkspider.py,搭建爬虫程序的基础架子。
import scrapy
from scrapy.http import Request
class GrouplinkspiderSpider(scrapy.Spider):
name = 'grouplinkspider'
allowed_domains = []
start_urls = []
def parse(self, response):
pass
(2)分析Google搜索结果页,编写对应爬虫
通过对Google搜素结果页源码的分析,发现我们所需要的网页a标签并没有任何特殊性的标识,所以用最粗暴的办法将所有的a标签都爬下来然后对href字段进行过滤。
def parse(self, response):
urls = response.xpath('//a/@href')
for url in urls:
strurl = url.extract()
//筛选除链接中包含http且不包含google字段的链接
if 'http' in strurl and 'google' not in strurl:
//使用Request方法执行进一步爬虫
yield Request(strurl,callback=self.getGroup)
接下来对系列关键词和搜索结果分页的循环爬取。
新建keywords.py文件。
keywords = []
def getKeyWords(index):
return keywords[index]
def getKeyWordsCount():
return len(keywords)
引入keywords,并依次分页循环爬虫方法。
from .keywords import getKeyWords,getKeyWordsCount
class GrouplinkspiderSpider(scrapy.Spider):
name = 'grouplinkspider'
allowed_domains = []
url = "https://www.google.com/search?q="
keywordcount = 0
start_urls = [url+getKeyWords(0)+"&start=0"]
count = 0
//爬取最大页数
maxCount = 10
def parse(self, response):
//在日志文件中打印出爬取的url
self.logger.info('Parse function called on %s', response.url)
urls = response.xpath('//a/@href')
for url in urls:
strurl = url.extract()
if 'http' in strurl and 'google' not in strurl:
yield Request(strurl,callback=self.getGroup)
//当页数小于最大页数时加1,并循环执行爬虫函数
if self.count < self.maxCount :
self.count += 1
yield Request(self.url+getKeyWords(self.keywordcount)+"&start="+str(self.count*10),callback=self.parse)
//依次获取keywords,将页数置零,并循环执行爬虫函数
elif self.keywordcount < getKeyWordsCount():
self.count = 0
self.keywordcount += 1
yield Request(self.url+getKeyWords(self.keywordcount)+"&start=0",callback=self.parse)
最后对搜索结果网页群链接的爬取,由于每个网页的结构都不一样,所以也只能将所有的a标签爬取下来,然后对href进行过滤。
import re
from grouplink.items import GrouplinkItem
def getGroup(self, response):
links = response.xpath('//a/@href')
for link in links:
strlink = link.extract()
//过滤出包含https://chat.whatsapp.com/字段的链接
if "https://chat.whatsapp.com/" in strlink:
//使用正则切出有用的链接
pattern = re.compile(r"https://chat.whatsapp.com/invite/.{22}|https://chat.whatsapp.com/.{22}")
strlinks = pattern.findall(strlink)
for substrlink in strlinks:
//实例化item
item = GrouplinkItem()
item['link'] = substrlink
yield item
3、数据保存
现在我们需要的群链接已经爬取下来,然后只需要保存就行了,由于业务需求暂时只保存成excel文件,接下来会保存到后台数据库中。
pipelines.py
from openpyxl import Workbook
class GrouplinkPipeline(object):
def __init__(self):
self.wb = Workbook()
self.ws = self.wb.active
self.ws.append(['链接'])
def process_item(self, item, spider):
data = [item['link']]
self.ws.append(data)
self.wb.save('grouplink.xlsx')
return item
setting.py
ITEM_PIPELINES = {
'grouplink.pipelines.GrouplinkPipeline': 300,
}
4、(附)对于setting.py的配置
在爬取Google的时候遇到了机器人协议文件的限制,需要在setting文件中关闭机器人协议。
ROBOTSTXT_OBEY = False
对于输出日志的配置。
to_day = datetime.datetime.now()
log_file_path = "log/scrapy_{}_{}_{}.log".format(to_day.year,to_day.month,to_day.day)
LOG_LEVEL = "DEBUG"
LOG_FILE = log_file_path
反爬的一些措施。
//设置访问超时时间
DOWNLOAD_TIMEOUT = 200
//设置访问延时
DOWNLOAD_DELAY = 10
//设置不需要cookie
COOKIES_ENABLED = False
5、(附)简单粗暴的断点续爬
断点续爬是爬虫项目中比较重要的功能,一般的是实现方式是用数据库记录爬虫进度信息,具体实现参见网上的教程。在这个项目中,使用了一种简单粗暴的方式来实现断点续爬,将数据保存在文件中,每次爬虫开始和结束对文件的数据进行操作,具体实现如下。
(1)初始化数据
grouplinkspider.py
def __init__(self): #创建初始化函数
with open('./count.json', 'r') as f: #以只读的方式打开文件
fcount = json.load(f) #将json格式字符串解析为json类型
self.count = fcount['pagecount'] #将页数信息赋值给count变量
self.keywordscount = fcount['keywordscount'] #将关键词信息赋值给keywordscount变量
(2)记录数据
items.py
pagecount = scrapy.Field() #增加pagecount Item
keywordscount = scrapy.Field() #增加keywordscount Item
grouplinkspider.py
def getGroup(self, response):
for substrlink in strlinks:
item['pagecount'] = self.count #记录页数信息
item['keywordscount'] = self.keywordscount #记录关键词信息
(3)保存数据
pipenlines.py
def __init__(self):
self.pagecount = 0
self.keywordscount = 0
def process_item(self, item, spider):
self.pagecount = item['pagecount']
self.keywordscount = item['keywordscount']
def close_spider(self, spider):
count = {
'pagecount': self.pagecount,
'keywordscount': self.keywordscount
}
with open(',/count.json', 'w') as f: #以写的方式打开文件
json.dump(coun, f) #将数据保存到文件
更多推荐
所有评论(0)