Scrapy学習(四)マイクロブログデータの取得
前言
Scrapy学習(三)豆弁図書情報を這い出す
前編に続く.今回はログインしなければアクセスできない微博を登りに来ました.爬虫類のターゲットは、ユーザーの微博数、注目数、ファン数を取得することです.ユーザー関係図の作成(実装されていない)のためのデータ準備
の準備をサードパーティ製ライブラリ を取り付ける.インストールMongoDB weibo爬虫類プロジェクト を作成
Scrapyプロジェクトを作成する方法については、前の記事で説明したように、直接トピックに入ります.
Itemsの作成
Itemデータこの部分は個人情報、微博数、注目数、点数数などの基本情報だけでいいです.
Spiderの作成
爬虫類を便利にするために、私たちが登録した入り口は携帯電話版の微博
コードに注意すべき点はいくつかあります.
start_url
ここにはマイクロブログのuidを記入し、ユーザーによってはカスタムドメイン名(上記の図)があり、アクセスしてから本物のuid
REACTOR_THREADPOOL_MAXSIZE
Default:
CloseSpider
不要な継続的な爬虫接続に遭遇した場合(すでに爬虫したリンク、定義されたゾンビ粉リンクなど)、CloseSpiderを使用して現在の爬虫スレッドを閉じることができます.
middlewaresの作成
クッキーの取得方法の作成
ここはもともと携帯版の微博でアナログログインしようとしたのですが、どうやってコードを検証するかは難しいです.だから私は直接ネット上で誰かが書いた登録ページ版の微博のコードSinaSpiderを使って、この人はよく書いて、興味がある人は見に行くことができます.もう1人は、シミュレーションログイン(検証コード付き)を書いたテストで使用できます.ただ、私のプロジェクトにどのように埋め込むかまだ考えていません.
上陸-反爬虫類のこの部分はプロジェクト全体で最も難しい場所であるはずだ.私はまだよく分からないところがたくさんあります.後で研究している暇がある.
pipelinesの作成
こちらは主にどんなタイプのItemをその表に保存すればいいですか?
プログラムを実行すると、MongoDBに私たちのデータが表示されます.
まとめ が落下することを防止することができる. cookiesによるログイン失敗時にシミュレーションログインを試みたが,効果は望ましくなかった であった.はエージェントIPプールで虫登りを試みたが,試みの失敗は主に があまりできなかった.は将来D 3を利用する.jsは登ったデータを描き出す プロジェクトアドレス:weibo_spider
Scrapy学習(三)豆弁図書情報を這い出す
前編に続く.今回はログインしなければアクセスできない微博を登りに来ました.爬虫類のターゲットは、ユーザーの微博数、注目数、ファン数を取得することです.ユーザー関係図の作成(実装されていない)のためのデータ準備
の準備を
requests
とpymongo
Scrapyプロジェクトを作成する方法については、前の記事で説明したように、直接トピックに入ります.
Itemsの作成
Itemデータこの部分は個人情報、微博数、注目数、点数数などの基本情報だけでいいです.
class ProfileItem(Item):
"""
、 、
"""
_id = Field()
nick_name = Field()
profile_pic = Field()
tweet_stats = Field()
following_stats = Field()
follower_stats = Field()
sex = Field()
location = Field()
birthday = Field()
bio = Field()
class FollowingItem(Item):
"""
"""
_id = Field()
relationship = Field()
class FollowedItem(Item):
"""
"""
_id = Field()
relationship = Field()
Spiderの作成
爬虫類を便利にするために、私たちが登録した入り口は携帯電話版の微博
http://weibo.cn/
です.ここで、マイクロブログのuidは、ユーザ資料ページにアクセスすることによって、または注目されるhref
属性から取得することができる.class WeiboSpiderSpider(scrapy.Spider):
name = "weibo_spider"
allowed_domains = ["weibo.cn"]
url = "http://weibo.cn/"
start_urls = ['2634877355',...] # ID
task_set = set(start_urls) #
tasked_set = set() #
...
def start_requests(self):
while len(self.task_set) > 0 :
_id = self.task_set.pop()
if _id in self.tasked_set:
raise CloseSpider(reason=" %s "% (_id) )
self.tasked_set.add(_id)
info_url = self.url + _id
info_item = ProfileItem()
following_url = info_url + "/follow"
following_item = FollowingItem()
following_item["_id"] = _id
following_item["relationship"] = []
follower_url = info_url + "/fans"
follower_item = FollowedItem()
follower_item["_id"] = _id
follower_item["relationship"] = []
yield scrapy.Request(info_url, meta={"item":info_item}, callback=self.account_parse)
yield scrapy.Request(following_url, meta={"item":following_item}, callback=self.relationship_parse)
yield scrapy.Request(follower_url, meta={"item":follower_item}, callback=self.relationship_parse)
def account_parse(self, response):
item = response.meta["item"]
sel = scrapy.Selector(response)
profile_url = sel.xpath("//div[@class='ut']/a/@href").extract()[1]
counts = sel.xpath("//div[@class='u']/div[@class='tip2']").extract_first()
item['_id'] = re.findall(u'^/(\d+)/info',profile_url)[0]
item['tweet_stats'] = re.findall(u' \[(\d+)\]', counts)[0]
item['following_stats'] = re.findall(u' \[(\d+)\]', counts)[0]
item['follower_stats'] = re.findall(u' \[(\d+)\]', counts)[0]
if int(item['tweet_stats']) < 4500 and int(item['following_stats']) > 1000 and int(item['follower_stats']) < 500:
raise CloseSpider(" ")
yield scrapy.Request("http://weibo.cn"+profile_url, meta={"item": item},callback=self.profile_parse)
def profile_parse(self,response):
item = response.meta['item']
sel = scrapy.Selector(response)
info = sel.xpath("//div[@class='tip']/following-sibling::div[@class='c']").extract_first()
item["profile_pic"] = sel.xpath("//div[@class='c']/img/@src").extract_first()
item["nick_name"] = re.findall(u' :(.*?)
',info)[0]
item["sex"] = re.findall(u' :(.*?)
',info) and re.findall(u' :(.*?)
',info)[0] or ''
item["location"] = re.findall(u' :(.*?)
',info) and re.findall(u' :(.*?)
',info)[0] or ''
item["birthday"] = re.findall(u' :(.*?)
',info) and re.findall(u' :(.*?)
',info)[0] or ''
item["bio"] = re.findall(u' :(.*?)
',info) and re.findall(u' :(.*?)
',info)[0] or ''
yield item
def relationship_parse(self, response):
item = response.meta["item"]
sel = scrapy.Selector(response)
uids = sel.xpath("//table/tr/td[last()]/a[last()]/@href").extract()
new_uids = []
for uid in uids:
if "uid" in uid:
new_uids.append(re.findall('uid=(\d+)&',uid)[0])
else:
try:
new_uids.append(re.findall('/(\d+)', uid)[0])
except:
print('--------',uid)
pass
item["relationship"].extend(new_uids)
for i in new_uids:
if i not in self.tasked_set:
self.task_set.add(i)
next_page = sel.xpath("//*[@id='pagelist']/form/div/a[text()=' ']/@href").extract_first()
if next_page:
yield scrapy.Request("http://weibo.cn"+next_page, meta={"item": item},callback=self.relationship_parse)
else:
yield item
コードに注意すべき点はいくつかあります.
start_url
ここにはマイクロブログのuidを記入し、ユーザーによってはカスタムドメイン名(上記の図)があり、アクセスしてから本物のuid
start_url
が記入される初期シード数は10個以上である.これは、後で私たちが登った新しい種が、登っていく列に加わることを確保するためです.10個以上の規定はScrapyドキュメントから調べたものですREACTOR_THREADPOOL_MAXSIZE
Default:
10
スレッド数はTwisted
スレッドプールのデフォルトサイズです(The maximum limit for Twisted Reactor thread pool size.)CloseSpider
不要な継続的な爬虫接続に遭遇した場合(すでに爬虫したリンク、定義されたゾンビ粉リンクなど)、CloseSpiderを使用して現在の爬虫スレッドを閉じることができます.
middlewaresの作成
class CookiesMiddleware(object):
""" Cookie """
def process_request(self, request, spider):
cookie = random.choice(cookies)
request.cookies = cookie
クッキーの取得方法の作成
ここはもともと携帯版の微博でアナログログインしようとしたのですが、どうやってコードを検証するかは難しいです.だから私は直接ネット上で誰かが書いた登録ページ版の微博のコードSinaSpiderを使って、この人はよく書いて、興味がある人は見に行くことができます.もう1人は、シミュレーションログイン(検証コード付き)を書いたテストで使用できます.ただ、私のプロジェクトにどのように埋め込むかまだ考えていません.
# encoding=utf-8
import json
import base64
import requests
myWeiBo = [
{'no': '[email protected]', 'psw': 'xx'},
{'no': '[email protected]', 'psw': 'xx'},
]
def getCookies(weibo):
""" Cookies """
cookies = []
loginURL = r'https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.15)'
for elem in weibo:
account = elem['no']
password = elem['psw']
username = base64.b64encode(account.encode('utf-8')).decode('utf-8')
postData = {
"entry": "sso",
"gateway": "1",
"from": "null",
"savestate": "30",
"useticket": "0",
"pagerefer": "",
"vsnf": "1",
"su": username,
"service": "sso",
"sp": password,
"sr": "1440*900",
"encoding": "UTF-8",
"cdult": "3",
"domain": "sina.com.cn",
"prelt": "0",
"returntype": "TEXT",
}
session = requests.Session()
r = session.post(loginURL, data=postData)
jsonStr = r.content.decode('gbk')
info = json.loads(jsonStr)
if info["retcode"] == "0":
print("Get Cookie Success!( Account:%s )" % account)
cookie = session.cookies.get_dict()
cookies.append(cookie)
else:
print("Failed!( Reason:%s )" % info["reason"].encode("utf-8"))
return cookies
cookies = getCookies(myWeiBo)
上陸-反爬虫類のこの部分はプロジェクト全体で最も難しい場所であるはずだ.私はまだよく分からないところがたくさんあります.後で研究している暇がある.
pipelinesの作成
こちらは主にどんなタイプのItemをその表に保存すればいいですか?
class MongoDBPipeline(object):
def __init__(self):
connection = MongoClient(
host=settings['MONGODB_SERVER'],
port=settings['MONGODB_PORT']
)
db = connection[settings['MONGODB_DB']]
self.info = db[settings['INFO']]
self.following = db[settings['FOLLOWING']]
self.followed = db[settings['FOLLOWED']]
def process_item(self, item, spider):
if isinstance(item, ProfileItem):
self.info.insert(dict(item))
elif isinstance(item, FollowingItem):
self.following.insert(dict(item))
elif isinstance(item, FollowedItem):
self.followed.insert(dict(item))
log.msg("Weibo added to MongoDB database!",
level=log.DEBUG, spider=spider)
return item
プログラムを実行すると、MongoDBに私たちのデータが表示されます.
まとめ
settings
のうちDOWNLOAD_DELAY
に5を設けることで、マイクロブログBANによって